| 79 | providers: [{provide: MENU_COMPONENT, useExisting: Menu}], |
| 80 | }) |
| 81 | export class Menu<V> implements OnDestroy { |
| 82 | /** The DeferredContentAware host directive. */ |
| 83 | private readonly _deferredContentAware = inject(DeferredContentAware, {optional: true}); |
| 84 | |
| 85 | /** The collection of menu items. */ |
| 86 | readonly _collection = new SortedCollection<MenuItem<V>>(); |
| 87 | |
| 88 | /** The menu items that are direct children of this menu. */ |
| 89 | readonly _items: Signal<MenuItem<V>[]> = computed(() => |
| 90 | this._collection.orderedItems().filter(i => i.parent === this), |
| 91 | ); |
| 92 | |
| 93 | /** A reference to the host element. */ |
| 94 | private readonly _elementRef = inject(ElementRef); |
| 95 | |
| 96 | /** A reference to the host element. */ |
| 97 | readonly element = this._elementRef.nativeElement as HTMLElement; |
| 98 | |
| 99 | /** The directionality (LTR / RTL) context for the application (or a subtree of it). */ |
| 100 | readonly textDirection = inject(Directionality).valueSignal; |
| 101 | |
| 102 | /** The unique ID of the menu. */ |
| 103 | readonly id = input(inject(_IdGenerator).getId('ng-menu-', true)); |
| 104 | |
| 105 | /** Whether the menu should wrap its items. */ |
| 106 | readonly wrap = input(true, {transform: booleanAttribute}); |
| 107 | |
| 108 | /** The delay in milliseconds before the typeahead buffer is cleared. */ |
| 109 | readonly typeaheadDelay = input<number>(500); // Picked arbitrarily. |
| 110 | |
| 111 | /** Whether the menu is disabled. */ |
| 112 | readonly disabled = input(false, {transform: booleanAttribute}); |
| 113 | |
| 114 | /** A reference to the parent menu item or menu trigger. */ |
| 115 | readonly parent = signal<MenuTrigger<V> | MenuItem<V> | undefined>(undefined); |
| 116 | |
| 117 | /** Whether the menu is soft disabled. */ |
| 118 | readonly softDisabled = input(true, {transform: booleanAttribute}); |
| 119 | |
| 120 | /** The menu ui pattern instance. */ |
| 121 | readonly _pattern: MenuPattern<V>; |
| 122 | |
| 123 | /** |
| 124 | * The menu item patterns for the menu items that are direct children of this menu, passed |
| 125 | * to the menu pattern. |
| 126 | * |
| 127 | * Note: contentChildren has an issue where it will return a successively smaller list |
| 128 | * each time that the menu is open and closed, eventually resulting in an empty list. |
| 129 | * The workaround is to trigger a recomputation of this signal whenever the menu is opened |
| 130 | * or closed, by calling this._pattern.visible() in the signal body. Otherwise, computed could |
| 131 | * not be used and would have to rebuild the list each time this method is called. |
| 132 | */ |
| 133 | private readonly _itemPatterns = computed(() => { |
| 134 | // Only needed to force a recompute. |
| 135 | this._pattern.visible(); |
| 136 | |
| 137 | return this._items().map(i => i._pattern); |
| 138 | }); |
nothing calls this directly
no test coverage detected
searching dependent graphs…