@ifsworld/granite-components 18.0.2-beta.1 → 18.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, ElementRef, ChangeDetectionStrategy, Component, Input, ContentChildren, HostBinding, NgModule, Renderer2, InjectionToken, HostAttributeToken, HostListener, Directive, EventEmitter, ChangeDetectorRef, QueryList, TemplateRef, ContentChild, Output, ViewChild, ViewContainerRef, NgZone, Injectable, Optional, Pipe } from '@angular/core';
2
+ import { inject, ElementRef, ChangeDetectionStrategy, Component, Input, ContentChildren, HostBinding, NgModule, Renderer2, InjectionToken, Injectable, HostAttributeToken, HostListener, Directive, EventEmitter, ChangeDetectorRef, QueryList, TemplateRef, ContentChild, Output, ViewChild, ViewContainerRef, NgZone, Optional, Pipe } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { CommonModule, DOCUMENT } from '@angular/common';
5
5
  import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
@@ -665,55 +665,51 @@ const graniteMenuTouchAnimations = {
665
665
  const GRANITE_MENU_PANEL = new InjectionToken('GRANITE_MENU_PANEL');
666
666
 
667
667
  /**
668
- * Utility class to manage a stack of open menus for touch devices.
669
- * This ensures that when clicking outside or closing, only the topmost menu closes.
668
+ * Stack of open touch menus so outside-click / close affects only the top
669
+ * panel.
670
670
  */
671
- class MenuStack {
672
- static { this.stack = []; }
673
- /**
674
- * Push a menu onto the stack when it opens
675
- */
676
- static push(menu) {
677
- const index = this.stack.indexOf(menu);
671
+ class GraniteMenuStackService {
672
+ constructor() {
673
+ this.stack = [];
674
+ }
675
+ /** Push a menu onto the stack when it opens */
676
+ push(menu) {
677
+ const index = this.stack.findIndex((m) => m.panelId === menu.panelId);
678
678
  if (index === -1) {
679
679
  this.stack.push(menu);
680
680
  }
681
681
  }
682
- /**
683
- * Remove a menu from the stack when it closes
684
- */
685
- static pop(menu) {
686
- const index = this.stack.indexOf(menu);
682
+ /** Remove a menu from the stack when it closes */
683
+ pop(menu) {
684
+ const index = this.stack.findIndex((m) => m.panelId === menu.panelId);
687
685
  if (index !== -1) {
688
686
  this.stack.splice(index, 1);
689
687
  }
690
688
  }
691
- /**
692
- * Get the topmost menu in the stack
693
- */
694
- static getTop() {
689
+ /** Topmost menu in the stack */
690
+ getTop() {
695
691
  return this.stack.length > 0 ? this.stack[this.stack.length - 1] : null;
696
692
  }
697
- /**
698
- * Check if a menu is the topmost one
699
- */
700
- static isTop(menu) {
693
+ /** Whether the menu is the topmost one */
694
+ isTop(menu) {
701
695
  const top = this.getTop();
702
696
  return top !== null && top.panelId === menu.panelId;
703
697
  }
704
- /**
705
- * Clear the entire stack (useful for cleanup)
706
- */
707
- static clear() {
698
+ /** Clear the stack (e.g. tests) */
699
+ clear() {
708
700
  this.stack = [];
709
701
  }
710
- /**
711
- * Get the current stack size
712
- */
713
- static size() {
702
+ /** Current stack depth */
703
+ size() {
714
704
  return this.stack.length;
715
705
  }
706
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GraniteMenuStackService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
707
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GraniteMenuStackService, providedIn: 'root' }); }
716
708
  }
709
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: GraniteMenuStackService, decorators: [{
710
+ type: Injectable,
711
+ args: [{ providedIn: 'root' }]
712
+ }] });
717
713
 
718
714
  /**
719
715
  * @license
@@ -967,6 +963,7 @@ class _MenuBaseComponent {
967
963
  /** Emits whenever an animation on the menu completes. */
968
964
  this._animationDone = new Subject();
969
965
  this._changeDetectorRef = inject(ChangeDetectorRef);
966
+ this._menuStack = inject(GraniteMenuStackService);
970
967
  this._menuEmpty$ = new BehaviorSubject(false);
971
968
  // eslint-disable-next-line @typescript-eslint/member-ordering
972
969
  this._isMenuEmpty$ = combineLatest([
@@ -1211,7 +1208,7 @@ class _MenuBaseComponent {
1211
1208
  //#region --- Touch device customizations ---
1212
1209
  if (this._clientOutput?.device === 'touch') {
1213
1210
  event?.stopPropagation();
1214
- if (!MenuStack.isTop(this)) {
1211
+ if (!this._menuStack.isTop(this)) {
1215
1212
  return;
1216
1213
  }
1217
1214
  }
@@ -1428,6 +1425,7 @@ class GraniteMenuTriggerForDirective {
1428
1425
  });
1429
1426
  this._dir = inject(Directionality, { optional: true });
1430
1427
  this._focusMonitor = inject(FocusMonitor);
1428
+ this._menuStack = inject(GraniteMenuStackService);
1431
1429
  this._touchTouchingElement = false;
1432
1430
  /**
1433
1431
  * Handles touch start events on the trigger.
@@ -1546,7 +1544,7 @@ class GraniteMenuTriggerForDirective {
1546
1544
  this.removeOverlayListeners();
1547
1545
  // Remove from stack on destroy
1548
1546
  if (this.menu && this._clientOutput?.device === 'touch') {
1549
- MenuStack.pop(this.menu);
1547
+ this._menuStack.pop(this.menu);
1550
1548
  }
1551
1549
  //#endregion --- Touch device customizations ---
1552
1550
  this._overlayRef.dispose();
@@ -1572,7 +1570,7 @@ class GraniteMenuTriggerForDirective {
1572
1570
  // Get rid of the menu and tell any parent to restore its position
1573
1571
  if (this._clientOutput.device === 'touch') {
1574
1572
  // Remove from stack when closing
1575
- MenuStack.pop(this.menu);
1573
+ this._menuStack.pop(this.menu);
1576
1574
  // First we wait for any running animation to complete
1577
1575
  const runningAnimationDone = this.menu._isAnimating
1578
1576
  ? this.menu._animationDone
@@ -1687,7 +1685,7 @@ class GraniteMenuTriggerForDirective {
1687
1685
  //#region --- Touch device customizations ---
1688
1686
  // Add menu to stack when opening on touch devices
1689
1687
  if (this._clientOutput.device === 'touch') {
1690
- MenuStack.push(this.menu);
1688
+ this._menuStack.push(this.menu);
1691
1689
  }
1692
1690
  //#endregion --- Touch device customizations ---
1693
1691
  this._setIsMenuOpen(true);
@@ -1954,7 +1952,7 @@ class GraniteMenuTriggerForDirective {
1954
1952
  const outsideClick = this._clientOutput.device === 'touch'
1955
1953
  ? fromEvent(this._document, 'click').pipe(filter((e) => e.target !== this._element.nativeElement &&
1956
1954
  e.target.closest('.granite-menu') === null &&
1957
- MenuStack.isTop(this.menu)), filter(() => !this.menu._isAnimating))
1955
+ this._menuStack.isTop(this.menu)), filter(() => !this.menu._isAnimating))
1958
1956
  : !this._parentMenu
1959
1957
  ? fromEvent(this._document, 'click').pipe(filter((e) => e.target !== this._element.nativeElement &&
1960
1958
  e.target.closest('.granite-menu') === null), filter(() => !this.menu._isAnimating))