@acorex/components 21.0.2-next.43 → 21.0.2-next.45

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.
@@ -2,11 +2,11 @@ import { NXClickEvent, NXComponent, AXComponent, NXEvent } from '@acorex/cdk/com
2
2
  import { AXDecoratorGenericComponent, AXDecoratorIconComponent } from '@acorex/components/decorators';
3
3
  import { isBrowser } from '@acorex/core/platform';
4
4
  import { AXTranslatorPipe } from '@acorex/core/translation';
5
- import { AXUnsubscriber, AXHtmlUtil } from '@acorex/core/utils';
5
+ import { AXHtmlUtil, AXUnsubscriber } from '@acorex/core/utils';
6
6
  import { AXZIndexService } from '@acorex/core/z-index';
7
7
  import { isPlatformBrowser, NgTemplateOutlet, AsyncPipe } from '@angular/common';
8
8
  import * as i0 from '@angular/core';
9
- import { Injectable, signal, inject, Renderer2, Injector, computed, output, input, afterNextRender, HostBinding, HostListener, ChangeDetectionStrategy, ViewEncapsulation, Component, DOCUMENT, PLATFORM_ID, DestroyRef, NgModule } from '@angular/core';
9
+ import { inject, DestroyRef, DOCUMENT, PLATFORM_ID, Injectable, signal, computed, contentChildren, Renderer2, Injector, output, input, afterNextRender, HostBinding, HostListener, ChangeDetectionStrategy, ViewEncapsulation, Component, NgModule } from '@angular/core';
10
10
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
11
11
  import { Router, NavigationStart } from '@angular/router';
12
12
  import { filter } from 'rxjs/operators';
@@ -18,16 +18,81 @@ class AXMenuService {
18
18
  this.closeAll$ = new Subject();
19
19
  this.open$ = new Subject();
20
20
  this.close$ = new Subject();
21
- this.closeExcept$ = new Subject();
22
21
  this.openContextMenu$ = new Subject();
23
22
  this.closeAllContextMenu$ = new Subject();
23
+ this.destroyRef = inject(DestroyRef);
24
+ this.document = inject(DOCUMENT);
25
+ this.platformId = inject(PLATFORM_ID);
26
+ this.openItems = new Set();
27
+ this.globalListenersBound = false;
28
+ this.scrollableParents = [];
29
+ this.onDocumentClick = (event) => {
30
+ if (this.rootElement && !this.rootElement.contains(event.target)) {
31
+ this.closeAll$.next();
32
+ }
33
+ };
34
+ this.onWindowOrScrollEvent = () => {
35
+ this.closeAll$.next();
36
+ };
37
+ this.closeAll$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
38
+ this.openItems.clear();
39
+ });
40
+ }
41
+ /**
42
+ * Registers a single set of document/window/scroll listeners for the whole menu tree.
43
+ */
44
+ initGlobalListeners(rootElement) {
45
+ if (!isPlatformBrowser(this.platformId) || this.globalListenersBound) {
46
+ return;
47
+ }
48
+ this.globalListenersBound = true;
49
+ this.rootElement = rootElement;
50
+ this.document.addEventListener('click', this.onDocumentClick);
51
+ window.addEventListener('scroll', this.onWindowOrScrollEvent, { capture: true });
52
+ window.addEventListener('resize', this.onWindowOrScrollEvent);
53
+ this.scrollableParents = AXHtmlUtil.getScrollableParents(rootElement);
54
+ this.scrollableParents.forEach((parent) => {
55
+ parent.addEventListener('scroll', this.onWindowOrScrollEvent);
56
+ });
57
+ this.destroyRef.onDestroy(() => {
58
+ this.document.removeEventListener('click', this.onDocumentClick);
59
+ window.removeEventListener('scroll', this.onWindowOrScrollEvent, { capture: true });
60
+ window.removeEventListener('resize', this.onWindowOrScrollEvent);
61
+ this.scrollableParents.forEach((parent) => {
62
+ parent.removeEventListener('scroll', this.onWindowOrScrollEvent);
63
+ });
64
+ });
65
+ }
66
+ /**
67
+ * Closes open submenus that are not on the ancestor path of the item being opened.
68
+ */
69
+ closeExcept(opener) {
70
+ const keepOpen = new Set();
71
+ let current = opener;
72
+ while (current) {
73
+ keepOpen.add(current);
74
+ current = current.parent;
75
+ }
76
+ for (const openItem of [...this.openItems]) {
77
+ if (!keepOpen.has(openItem)) {
78
+ this.markClosed(openItem);
79
+ }
80
+ }
81
+ }
82
+ markOpen(item) {
83
+ this.openItems.add(item);
84
+ this.open$.next(item);
85
+ }
86
+ markClosed(item) {
87
+ this.openItems.delete(item);
88
+ this.close$.next(item);
24
89
  }
25
90
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
26
91
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuService }); }
27
92
  }
28
93
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuService, decorators: [{
29
94
  type: Injectable
30
- }] });
95
+ }], ctorParameters: () => [] });
31
96
 
32
97
  class AXRootMenu {
33
98
  }
@@ -48,12 +113,14 @@ class AXMenuItemComponent extends NXComponent {
48
113
  constructor() {
49
114
  super();
50
115
  this.isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
51
- this.hasSubItems = signal(false, ...(ngDevMode ? [{ debugName: "hasSubItems" }] : /* istanbul ignore next */ []));
52
- this.isFirstLevel = signal(false, ...(ngDevMode ? [{ debugName: "isFirstLevel" }] : /* istanbul ignore next */ []));
116
+ this.submenuRendered = signal(false, ...(ngDevMode ? [{ debugName: "submenuRendered" }] : /* istanbul ignore next */ []));
117
+ this.parent = inject(AXMenuItemComponent, { optional: true, skipSelf: true });
118
+ this.isRoot = computed(() => this.parent == null, ...(ngDevMode ? [{ debugName: "isRoot" }] : /* istanbul ignore next */ []));
119
+ this.isFirstLevel = computed(() => this.parent == null, ...(ngDevMode ? [{ debugName: "isFirstLevel" }] : /* istanbul ignore next */ []));
120
+ this.childMenuItems = contentChildren(AXMenuItemComponent, { ...(ngDevMode ? { debugName: "childMenuItems" } : /* istanbul ignore next */ {}), descendants: false });
121
+ this.hasSubItems = computed(() => this.childMenuItems().length > 0, ...(ngDevMode ? [{ debugName: "hasSubItems" }] : /* istanbul ignore next */ []));
53
122
  this.root = inject(AXRootMenu);
54
- this.isRoot = () => this.parent == null;
55
123
  this.service = inject(AXMenuService);
56
- this.scrollableParents = [];
57
124
  this.unsuscriber = inject(AXUnsubscriber);
58
125
  this.renderer = inject(Renderer2);
59
126
  this.injector = inject(Injector);
@@ -72,13 +139,7 @@ class AXMenuItemComponent extends NXComponent {
72
139
  this.data = input(...(ngDevMode ? [undefined, { debugName: "data" }] : /* istanbul ignore next */ []));
73
140
  this.disabled = input(...(ngDevMode ? [undefined, { debugName: "disabled" }] : /* istanbul ignore next */ []));
74
141
  this.color = input(...(ngDevMode ? [undefined, { debugName: "color" }] : /* istanbul ignore next */ []));
75
- //
76
- afterNextRender(() => {
77
- this.detectSubItems();
78
- this.observeMutations();
79
- this.bindScrollEvents();
80
- });
81
- //
142
+ this.mouseLeaveTimeout = null;
82
143
  this.service.closeAll$.pipe(this.unsuscriber.takeUntilDestroy).subscribe(() => this.close());
83
144
  this.service.open$.pipe(this.unsuscriber.takeUntilDestroy).subscribe((item) => {
84
145
  if (this === item) {
@@ -86,89 +147,34 @@ class AXMenuItemComponent extends NXComponent {
86
147
  this.schedulePositionCalculation();
87
148
  }
88
149
  });
89
- //
90
150
  this.service.close$.pipe(this.unsuscriber.takeUntilDestroy).subscribe((item) => {
91
151
  if (this == item) {
92
152
  this.isOpen.set(false);
93
153
  }
94
154
  });
95
- //
96
- this.service.closeExcept$.pipe(this.unsuscriber.takeUntilDestroy).subscribe((item) => {
97
- this.closeExcept(item);
98
- });
99
- }
100
- closeExcept(item) {
101
- const list = [item];
102
- // TODO: Check for better solution
103
- const parentEl = this.nativeElement.parentElement?.parentElement;
104
- this.parent = parentEl?.tagName == 'AX-MENU-ITEM' ? parentEl?.['__axContext__'] : null;
105
- //
106
- let parent = item.parent;
107
- while (parent != null) {
108
- list.push(parent);
109
- parent = parent.parent;
110
- }
111
- //
112
- if (!list.includes(this)) {
113
- this.close();
114
- }
115
- }
116
- observeMutations() {
117
- this.mutationObserver = new MutationObserver(() => {
118
- this.detectSubItems();
119
- });
120
- // Start observing changes in child elements
121
- this.mutationObserver.observe(this.nativeElement, {
122
- childList: true,
123
- subtree: true,
124
- });
125
155
  }
126
156
  getText() {
127
157
  return this.nativeElement.querySelector('ax-text')?.innerText;
128
158
  }
129
- /**
130
- * Manually detect all `ax-menu-item` elements and check if this menu item has sub-items.
131
- */
132
- detectSubItems() {
133
- //
134
- const parentEl = this.nativeElement.parentElement?.parentElement;
135
- this.parent = parentEl?.tagName == 'AX-MENU-ITEM' ? parentEl?.['__axContext__'] : null;
136
- //
137
- const tag = this.nativeElement.parentElement?.tagName;
138
- this.isFirstLevel.set(tag == 'AX-MENU' || tag == 'AX-CONTEXT-MENU');
139
- const subItems = this.nativeElement.querySelectorAll('ax-menu-item');
140
- if (subItems.length > 0) {
141
- this.hasSubItems.set(true);
142
- }
143
- else {
144
- this.hasSubItems.set(false);
145
- }
146
- }
147
159
  /**
148
160
  * Opens the submenu of this menu item if it has sub-items and is not disabled.
149
- *
150
- * Inherited behavior: Uses the injected service to notify other items to close.
151
- *
152
- * @returns void - No return value. Triggers submenu opening side-effects.
153
161
  */
154
162
  open() {
155
- this.service.closeExcept$.next(this);
156
- if (!this.disabled() && this.hasSubItems()) {
157
- // Acquire z-index token for this submenu
158
- if (!this.zToken) {
159
- this.zToken = this.zIndexService.acquire();
160
- }
161
- this.service.open$.next(this);
163
+ if (this.disabled() || !this.hasSubItems()) {
164
+ return;
162
165
  }
166
+ this.submenuRendered.set(true);
167
+ this.service.closeExcept(this);
168
+ if (!this.zToken) {
169
+ this.zToken = this.zIndexService.acquire();
170
+ }
171
+ this.service.markOpen(this);
163
172
  }
164
173
  /**
165
174
  * Closes the submenu of this menu item if open.
166
- *
167
- * @returns void - No return value. Triggers submenu closing side-effects.
168
175
  */
169
176
  close() {
170
- this.service.close$.next(this);
171
- // Release z-index token
177
+ this.service.markClosed(this);
172
178
  this.zIndexService.release(this.zToken);
173
179
  this.zToken = null;
174
180
  }
@@ -176,10 +182,14 @@ class AXMenuItemComponent extends NXComponent {
176
182
  * Positions the submenu after layout so nested levels measure their full height.
177
183
  */
178
184
  schedulePositionCalculation() {
179
- this.calculatePosition();
180
185
  afterNextRender(() => {
181
186
  if (this.isOpen()) {
182
187
  this.calculatePosition();
188
+ afterNextRender(() => {
189
+ if (this.isOpen()) {
190
+ this.calculatePosition();
191
+ }
192
+ }, { injector: this.injector });
183
193
  }
184
194
  }, { injector: this.injector });
185
195
  }
@@ -197,11 +207,10 @@ class AXMenuItemComponent extends NXComponent {
197
207
  const isRtl = AXHtmlUtil.isRtl(this.nativeElement);
198
208
  let finalTop;
199
209
  let finalLeft;
200
- // --- 1. VERTICAL POSITIONING ---
201
210
  const preferredTop = this.isFirstLevel() && this.root.orientation() === 'horizontal'
202
- ? itemRect.bottom // For horizontal menu, open below
203
- : itemRect.top; // For vertical menu, align with parent top
204
- const alternateTop = itemRect.top - submenuRect.height; // Position for opening upwards
211
+ ? itemRect.bottom
212
+ : itemRect.top;
213
+ const alternateTop = itemRect.top - submenuRect.height;
205
214
  if (preferredTop + submenuRect.height <= windowHeight) {
206
215
  finalTop = preferredTop;
207
216
  }
@@ -212,7 +221,6 @@ class AXMenuItemComponent extends NXComponent {
212
221
  finalTop = windowHeight - submenuRect.height;
213
222
  }
214
223
  finalTop = this.clampVerticalPosition(finalTop, submenuRect.height, windowHeight);
215
- // --- 2. HORIZONTAL POSITIONING ---
216
224
  if (this.isFirstLevel() && this.root.orientation() === 'horizontal') {
217
225
  const preferredLeft = isRtl ? itemRect.right - submenuRect.width : itemRect.left;
218
226
  const alternateLeft = isRtl ? itemRect.left : itemRect.right - submenuRect.width;
@@ -251,7 +259,6 @@ class AXMenuItemComponent extends NXComponent {
251
259
  }
252
260
  }
253
261
  }
254
- // --- 3. OVERLAP-AWARE VERTICAL SHIFT ---
255
262
  const isNestedMenu = !(this.isFirstLevel() && this.root.orientation() === 'horizontal');
256
263
  if (isNestedMenu) {
257
264
  const overlapsParent = finalLeft < itemRect.right && itemRect.left < finalLeft + submenuRect.width;
@@ -263,11 +270,9 @@ class AXMenuItemComponent extends NXComponent {
263
270
  }
264
271
  }
265
272
  finalTop = this.clampVerticalPosition(finalTop, submenuRect.height, windowHeight);
266
- // --- 4. APPLY FINAL STYLES ---
267
273
  this.renderer.setStyle(submenu, 'position', 'fixed');
268
274
  this.renderer.setStyle(submenu, 'top', `${finalTop}px`);
269
275
  this.renderer.setStyle(submenu, 'left', `${finalLeft}px`);
270
- // Apply z-index from token
271
276
  if (this.zToken) {
272
277
  this.renderer.setStyle(submenu, 'z-index', String(this.zToken.zIndex));
273
278
  }
@@ -295,7 +300,6 @@ class AXMenuItemComponent extends NXComponent {
295
300
  e.stopPropagation();
296
301
  if (this.disabled())
297
302
  return;
298
- //
299
303
  const event = {
300
304
  sender: this,
301
305
  nativeEvent: e,
@@ -306,10 +310,8 @@ class AXMenuItemComponent extends NXComponent {
306
310
  data: this.data(),
307
311
  },
308
312
  };
309
- //
310
313
  this.onClick.emit(event);
311
314
  this.root.onItemClick.emit({ ...event, ...{ sender: this.root } });
312
- //
313
315
  if (this.hasSubItems() && !event.canceled) {
314
316
  this.open();
315
317
  }
@@ -320,10 +322,9 @@ class AXMenuItemComponent extends NXComponent {
320
322
  }
321
323
  handleMouseEnter(event) {
322
324
  event.stopPropagation();
323
- // Cancel the close delay if the mouse re-enters the element
324
325
  if (this.mouseLeaveTimeout) {
325
326
  clearTimeout(this.mouseLeaveTimeout);
326
- this.mouseLeaveTimeout = null; // Reset the timeout
327
+ this.mouseLeaveTimeout = null;
327
328
  }
328
329
  if (!this.isFirstLevel() || this.root.openOn() == 'hover') {
329
330
  this.open();
@@ -332,48 +333,18 @@ class AXMenuItemComponent extends NXComponent {
332
333
  handleMouseLeave(event) {
333
334
  event.stopPropagation();
334
335
  if (this.hasSubItems() && this.root.closeOn() === 'leave') {
335
- // Clear any previous timeout to avoid multiple triggers
336
336
  if (this.mouseLeaveTimeout) {
337
337
  clearTimeout(this.mouseLeaveTimeout);
338
338
  }
339
- // Set a delay before closing the submenu
340
339
  this.mouseLeaveTimeout = setTimeout(() => {
341
340
  this.close();
342
- }, 500); // Adjust the delay (500ms in this case) as per your requirement
343
- }
344
- }
345
- onWindowEvent() {
346
- this.service.closeAll$.next(); // Close all menus on scroll or resize
347
- }
348
- /**
349
- * Close all menus if clicking outside the root menu and all sub-items.
350
- */
351
- onClickOutside(event) {
352
- const hostElement = this.root.nativeElement;
353
- if (!hostElement.contains(event.target)) {
354
- this.service.closeAll$.next(); // Close all menus if click is outside the root and sub-items
341
+ }, 500);
355
342
  }
356
343
  }
357
344
  ngOnDestroy() {
358
- this.removeScrollEvents();
359
- }
360
- bindScrollEvents() {
361
- this.scrollableParents = AXHtmlUtil.getScrollableParents(this.nativeElement);
362
- this.scrollableParents.forEach((parent) => {
363
- parent.addEventListener('scroll', this.onContainerScroll.bind(this));
364
- });
365
- }
366
- // Remove scroll event listeners
367
- removeScrollEvents() {
368
- this.scrollableParents.forEach((parent) => {
369
- parent.removeEventListener('scroll', this.onContainerScroll.bind(this));
370
- });
371
- }
372
- /**
373
- * Handler for scroll events (window or scrollable parent containers)
374
- */
375
- onContainerScroll() {
376
- this.service.closeAll$.next(); // Close all menus on scroll
345
+ if (this.isOpen()) {
346
+ this.close();
347
+ }
377
348
  }
378
349
  /** @ignore */
379
350
  get __hostClass() {
@@ -385,7 +356,7 @@ class AXMenuItemComponent extends NXComponent {
385
356
  return list;
386
357
  }
387
358
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
388
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMenuItemComponent, isStandalone: true, selector: "ax-menu-item", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClick: "onClick" }, host: { listeners: { "click": "handleClick($event)", "mouseenter": "handleMouseEnter($event)", "mouseleave": "handleMouseLeave($event)", "window:scroll": "onWindowEvent()", "window:resize": "onWindowEvent()", "document:click": "onClickOutside($event)" }, properties: { "class": "this.__hostClass" } }, providers: [
359
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMenuItemComponent, isStandalone: true, selector: "ax-menu-item", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onClick: "onClick" }, host: { listeners: { "click": "handleClick($event)", "mouseenter": "handleMouseEnter($event)", "mouseleave": "handleMouseLeave($event)" }, properties: { "class": "this.__hostClass" } }, providers: [
389
360
  {
390
361
  provide: AXMenuItemComponentBase,
391
362
  useExisting: AXMenuItemComponent,
@@ -395,7 +366,7 @@ class AXMenuItemComponent extends NXComponent {
395
366
  provide: AXComponent,
396
367
  useExisting: AXMenuItemComponent,
397
368
  },
398
- ], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-action-item-prefix\">\n <ng-content select=\"ax-prefix\"></ng-content>\n <ng-content select=\"ax-text\"></ng-content>\n</div>\n<div class=\"ax-action-item-suffix\">\n <ng-content select=\"ax-suffix\"></ng-content>\n @if (hasSubItems() && (!isRoot() || root?.hasArrow())) {\n <i class=\"ax-icon ax-icon-solid {{ arrowIcon() }} \"></i>\n }\n</div>\n<div class=\"ax-menu-items ax-action-list ax-action-list-vertical\" [class.ax-state-open]=\"isOpen()\">\n <ng-content select=\"ax-menu-item,ax-title,ax-divider,ng-container\"></ng-content>\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
369
+ ], queries: [{ propertyName: "childMenuItems", predicate: AXMenuItemComponent, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"ax-action-item-prefix\">\n <ng-content select=\"ax-prefix\"></ng-content>\n <ng-content select=\"ax-text\"></ng-content>\n</div>\n<div class=\"ax-action-item-suffix\">\n <ng-content select=\"ax-suffix\"></ng-content>\n @if (hasSubItems() && (!isRoot() || root.hasArrow())) {\n <i class=\"ax-icon ax-icon-solid {{ arrowIcon() }} \"></i>\n }\n</div>\n<div class=\"ax-menu-items ax-action-list ax-action-list-vertical\" [class.ax-state-open]=\"isOpen()\">\n @if (submenuRendered()) {\n <ng-content select=\"ax-menu-item,ax-title,ax-divider,ng-container\"></ng-content>\n }\n</div>\n", changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
399
370
  }
400
371
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuItemComponent, decorators: [{
401
372
  type: Component,
@@ -409,8 +380,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
409
380
  provide: AXComponent,
410
381
  useExisting: AXMenuItemComponent,
411
382
  },
412
- ], template: "<div class=\"ax-action-item-prefix\">\n <ng-content select=\"ax-prefix\"></ng-content>\n <ng-content select=\"ax-text\"></ng-content>\n</div>\n<div class=\"ax-action-item-suffix\">\n <ng-content select=\"ax-suffix\"></ng-content>\n @if (hasSubItems() && (!isRoot() || root?.hasArrow())) {\n <i class=\"ax-icon ax-icon-solid {{ arrowIcon() }} \"></i>\n }\n</div>\n<div class=\"ax-menu-items ax-action-list ax-action-list-vertical\" [class.ax-state-open]=\"isOpen()\">\n <ng-content select=\"ax-menu-item,ax-title,ax-divider,ng-container\"></ng-content>\n</div>\n" }]
413
- }], ctorParameters: () => [], propDecorators: { onClick: [{ type: i0.Output, args: ["onClick"] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], handleClick: [{
383
+ ], template: "<div class=\"ax-action-item-prefix\">\n <ng-content select=\"ax-prefix\"></ng-content>\n <ng-content select=\"ax-text\"></ng-content>\n</div>\n<div class=\"ax-action-item-suffix\">\n <ng-content select=\"ax-suffix\"></ng-content>\n @if (hasSubItems() && (!isRoot() || root.hasArrow())) {\n <i class=\"ax-icon ax-icon-solid {{ arrowIcon() }} \"></i>\n }\n</div>\n<div class=\"ax-menu-items ax-action-list ax-action-list-vertical\" [class.ax-state-open]=\"isOpen()\">\n @if (submenuRendered()) {\n <ng-content select=\"ax-menu-item,ax-title,ax-divider,ng-container\"></ng-content>\n }\n</div>\n" }]
384
+ }], ctorParameters: () => [], propDecorators: { childMenuItems: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AXMenuItemComponent), { ...{ descendants: false }, isSignal: true }] }], onClick: [{ type: i0.Output, args: ["onClick"] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], handleClick: [{
414
385
  type: HostListener,
415
386
  args: ['click', ['$event']]
416
387
  }], handleMouseEnter: [{
@@ -419,15 +390,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
419
390
  }], handleMouseLeave: [{
420
391
  type: HostListener,
421
392
  args: ['mouseleave', ['$event']]
422
- }], onWindowEvent: [{
423
- type: HostListener,
424
- args: ['window:scroll']
425
- }, {
426
- type: HostListener,
427
- args: ['window:resize']
428
- }], onClickOutside: [{
429
- type: HostListener,
430
- args: ['document:click', ['$event']]
431
393
  }], __hostClass: [{
432
394
  type: HostBinding,
433
395
  args: ['class']
@@ -478,6 +440,7 @@ class AXContextMenuComponent extends NXComponent {
478
440
  //
479
441
  afterNextRender(() => {
480
442
  this.bindContextEvent();
443
+ this.service.initGlobalListeners(this.nativeElement);
481
444
  });
482
445
  this.setupCloseOnRouteChange();
483
446
  this.service.closeAllContextMenu$.subscribe(() => {
@@ -803,7 +766,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
803
766
  */
804
767
  class AXMenuComponent extends NXComponent {
805
768
  constructor() {
806
- super(...arguments);
769
+ super();
807
770
  this.orientation = input('horizontal', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
808
771
  this.openOn = input('hover', ...(ngDevMode ? [{ debugName: "openOn" }] : /* istanbul ignore next */ []));
809
772
  this.closeOn = input('leave', ...(ngDevMode ? [{ debugName: "closeOn" }] : /* istanbul ignore next */ []));
@@ -811,6 +774,9 @@ class AXMenuComponent extends NXComponent {
811
774
  this.onItemClick = output();
812
775
  this.items = input([], ...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
813
776
  this.hasArrow = input(true, ...(ngDevMode ? [{ debugName: "hasArrow" }] : /* istanbul ignore next */ []));
777
+ afterNextRender(() => {
778
+ this.service.initGlobalListeners(this.nativeElement);
779
+ });
814
780
  }
815
781
  /** @ignore */
816
782
  get __hostClass() {
@@ -829,7 +795,7 @@ class AXMenuComponent extends NXComponent {
829
795
  close() {
830
796
  this.service.closeAll$.next();
831
797
  }
832
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
798
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
833
799
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXMenuComponent, isStandalone: true, selector: "ax-menu", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, openOn: { classPropertyName: "openOn", publicName: "openOn", isSignal: true, isRequired: false, transformFunction: null }, closeOn: { classPropertyName: "closeOn", publicName: "closeOn", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null }, hasArrow: { classPropertyName: "hasArrow", publicName: "hasArrow", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onItemClick: "onItemClick" }, host: { properties: { "class": "this.__hostClass" } }, providers: [
834
800
  AXMenuService,
835
801
  {
@@ -862,7 +828,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
862
828
  AsyncPipe,
863
829
  AXTranslatorPipe,
864
830
  ], template: "<ng-content select=\"ax-menu-item,ax-divider,ax-title,ng-container\"></ng-content>\n\n@for (node of items(); track node) {\n <ng-container [ngTemplateOutlet]=\"Recursion\" [ngTemplateOutletContext]=\"{ $implicit: node }\"> </ng-container>\n}\n\n<ng-template #Recursion let-item>\n @if (item.group?.title) {\n <ax-title>{{ item.group?.title }}</ax-title>\n }\n <ax-menu-item [name]=\"item.name\" [data]=\"item.data\" [disabled]=\"item.disabled\" [color]=\"item.color\">\n @if (item.icon) {\n <ax-prefix>\n <ax-icon [icon]=\"item.icon\"> </ax-icon>\n </ax-prefix>\n }\n @if (item.text) {\n <ax-text>{{ item.text | translate | async }}</ax-text>\n }\n @if (item.suffix) {\n <ax-suffix>\n <ax-text>{{ item.suffix.text | translate | async }}</ax-text>\n </ax-suffix>\n }\n @for (child of item.items; track child) {\n <ng-container [ngTemplateOutlet]=\"Recursion\" [ngTemplateOutletContext]=\"{ $implicit: child }\"></ng-container>\n }\n </ax-menu-item>\n @if (item.break) {\n <ax-divider></ax-divider>\n }\n</ng-template>\n", styles: ["ax-context-menu,ax-menu{width:max-content;color:inherit;display:flex}:is(ax-context-menu,ax-menu).ax-menu-container,:is(ax-context-menu,ax-menu) .ax-menu-items{visibility:hidden;width:max-content;height:max-content;min-width:calc(var(--spacing,.25rem) * 48);border-radius:var(--radius-default,var(--ax-sys-border-radius));border-style:solid;border-width:1px;border-color:var(--color-border-lightest,rgba(var(--ax-sys-color-border-lightest-surface)));background-color:var(--color-lightest,rgba(var(--ax-sys-color-lightest-surface)));color:var(--color-on-lightest,rgba(var(--ax-sys-color-on-lightest-surface)));padding-block:calc(var(--spacing,.25rem) * 2);opacity:0;transition-property:all;transition-duration:var(--ax-sys-transition-duration);transition-timing-function:var(--ax-sys-transition-timing-function);flex-direction:column;display:flex;position:fixed;box-shadow:0 1px 3px #0000001a,0 1px 2px -1px #0000001a}:is(:is(ax-context-menu,ax-menu).ax-menu-container,:is(ax-context-menu,ax-menu) .ax-menu-items).ax-state-open{visibility:visible;opacity:1}:is(:is(ax-context-menu,ax-menu).ax-menu-container,:is(ax-context-menu,ax-menu) .ax-menu-items) ax-menu-item{color:var(--ax-comp-bg)}:is(:is(ax-context-menu,ax-menu).ax-menu-container,:is(ax-context-menu,ax-menu) .ax-menu-items) ax-menu-item:hover:not(.ax-state-disabled){background-color:var(--ax-comp-bg);color:var(--ax-comp-bg)}:is(:is(ax-context-menu,ax-menu).ax-menu-container,:is(ax-context-menu,ax-menu) .ax-menu-items) ax-menu-item:hover:not(.ax-state-disabled) ax-suffix ax-text{color:var(--ax-comp-bg)}:is(:is(ax-context-menu,ax-menu).ax-menu-container,:is(ax-context-menu,ax-menu) .ax-menu-items) ax-menu-item ax-suffix ax-text{font-weight:400!important}ax-context-menu.ax-action-list-horizontal{padding-inline:calc(var(--spacing,.25rem) * 4)}ax-menu>ax-menu-item:has(>.ax-action-item-suffix:not(:empty)){gap:calc(var(--spacing,.25rem) * 2)}ax-menu.ax-action-list-horizontal{min-width:calc(var(--spacing,.25rem) * 48);gap:calc(var(--spacing,.25rem) * 5)}ax-menu.ax-action-list-horizontal>ax-title{display:none}ax-menu.ax-action-list-horizontal>ax-menu-item{font-weight:500}ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-prefix{padding-inline-start:0!important}ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-suffix:not(ax-menu.ax-action-list-horizontal>ax-menu-item>.ax-action-item-suffix:empty){margin-inline-end:0!important;padding-inline-start:0!important}ax-menu.ax-action-list-horizontal>ax-menu-item:hover:not(ax-menu.ax-action-list-horizontal>ax-menu-item.ax-state-disabled){background-color:#0000!important}ax-menu.ax-action-list-horizontal>ax-menu-item:hover:not(ax-menu.ax-action-list-horizontal>ax-menu-item.ax-state-disabled)>.ax-action-item-prefix,ax-menu.ax-action-list-horizontal>ax-menu-item:hover:not(ax-menu.ax-action-list-horizontal>ax-menu-item.ax-state-disabled)>.ax-action-item-suffix{opacity:.7}ax-menu.ax-action-list-vertical{width:max-content;min-width:calc(var(--spacing,.25rem) * 48)}ax-menu.ax-action-list-vertical>ax-menu-item{font-weight:500}ax-menu.ax-action-list-vertical>ax-menu-item:hover:not(ax-menu.ax-action-list-vertical>ax-menu-item.ax-state-disabled){background-color:#0000!important}ax-menu.ax-action-list-vertical>ax-menu-item:hover:not(ax-menu.ax-action-list-vertical>ax-menu-item.ax-state-disabled)>.ax-action-item-prefix,ax-menu.ax-action-list-vertical>ax-menu-item:hover:not(ax-menu.ax-action-list-vertical>ax-menu-item.ax-state-disabled)>.ax-action-item-suffix{opacity:.7}ax-menu>ax-menu-item{padding-block:calc(var(--spacing,.25rem) * 2)}ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item.ax-state-disabled){border-radius:var(--radius-default,var(--ax-sys-border-radius))}ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item.ax-state-disabled)>ax-icon,ax-menu>ax-menu-item:hover:not(ax-menu>ax-menu-item.ax-state-disabled)>ax-text{opacity:.7}\n"] }]
865
- }], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], openOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOn", required: false }] }], closeOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOn", required: false }] }], onItemClick: [{ type: i0.Output, args: ["onItemClick"] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], hasArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasArrow", required: false }] }], __hostClass: [{
831
+ }], ctorParameters: () => [], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], openOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "openOn", required: false }] }], closeOn: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOn", required: false }] }], onItemClick: [{ type: i0.Output, args: ["onItemClick"] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], hasArrow: [{ type: i0.Input, args: [{ isSignal: true, alias: "hasArrow", required: false }] }], __hostClass: [{
866
832
  type: HostBinding,
867
833
  args: ['class']
868
834
  }] } });