@ngrdt/menu 0.0.16 → 0.0.18

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,8 +1,8 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, ElementRef, DestroyRef, Renderer2, ChangeDetectorRef, Component, ChangeDetectionStrategy, ViewChildren, ViewChild, Input, HostBinding, HostListener, EnvironmentInjector, booleanAttribute, numberAttribute, Directive, ViewEncapsulation, QueryList, NgModule } from '@angular/core';
2
+ import { InjectionToken, inject, ElementRef, DestroyRef, Renderer2, ChangeDetectorRef, input, linkedSignal, computed, signal, untracked, effect, afterRenderEffect, afterNextRender, HostListener, ViewChild, ViewChildren, ChangeDetectionStrategy, Component, booleanAttribute, numberAttribute, EnvironmentInjector, Directive, ViewEncapsulation, QueryList, NgModule } from '@angular/core';
3
3
  import * as i1 from '@angular/common';
4
4
  import { DOCUMENT, CommonModule } from '@angular/common';
5
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
5
+ import { takeUntilDestroyed, toSignal, toObservable } from '@angular/core/rxjs-interop';
6
6
  import * as i2 from '@angular/router';
7
7
  import { Router, RouterModule } from '@angular/router';
8
8
  import * as i3 from '@ngrdt/router';
@@ -10,7 +10,7 @@ import { RdtRouterService, RdtAnyRouteActiveDirective } from '@ngrdt/router';
10
10
  import * as i4 from '@ngrdt/shortcuts';
11
11
  import { RdtShortcutService, RdtShortcut, RdtKeyListenerDirective } from '@ngrdt/shortcuts';
12
12
  import { RdtStringUtils, KB_CODE, RdtObjectUtils } from '@ngrdt/utils';
13
- import { delay, of, map, first, Subscription, fromEvent, throttleTime, animationFrameScheduler } from 'rxjs';
13
+ import { delay, of, map, first, fromEvent, throttleTime, animationFrameScheduler, switchMap, withLatestFrom } from 'rxjs';
14
14
  import { RDT_BUTTON_BASE_PROVIDER, RdtButtonOutletDirective } from '@ngrdt/button';
15
15
 
16
16
  var RdtMenuShortcutMode;
@@ -195,24 +195,25 @@ class RdtMenuOverlayComponent {
195
195
  children;
196
196
  focusableElements;
197
197
  menuItemContainer;
198
- item;
199
- level;
200
- preferredHorizontalDir = DEFAULT_MENU_HORIZONTAL_DIR;
201
- preferredVerticalDir = DEFAULT_MENU_VERTICAL_DIR;
202
- expanded = false;
203
- autofocusItem = null;
198
+ item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
199
+ level = input.required(...(ngDevMode ? [{ debugName: "level" }] : []));
200
+ preferredHorizontalDir = input(DEFAULT_MENU_HORIZONTAL_DIR, ...(ngDevMode ? [{ debugName: "preferredHorizontalDir" }] : []));
201
+ preferredVerticalDir = input(DEFAULT_MENU_VERTICAL_DIR, ...(ngDevMode ? [{ debugName: "preferredVerticalDir" }] : []));
202
+ expandedInput = input(false, ...(ngDevMode ? [{ debugName: "expandedInput", alias: 'expanded' }] : [{ alias: 'expanded' }]));
203
+ expanded = linkedSignal(() => this.expandedInput());
204
+ autofocusItemInput = input(null, ...(ngDevMode ? [{ debugName: "autofocusItemInput", alias: 'autofocusItem' }] : [{
205
+ alias: 'autofocusItem',
206
+ }]));
207
+ autofocusItem = linkedSignal(() => this.autofocusItemInput());
204
208
  // Element used to relatively position menu,
205
209
  // typically parent element.
206
210
  // If not specified, parent element is used.
207
- anchorElement;
208
- roleAttr = 'menu';
209
- tabindexAttr = '-1';
210
- get zIndex() {
211
- return this.level + 10;
212
- }
213
- get isRootLevel() {
214
- return this.level === 0;
215
- }
211
+ anchorElementInput = input(null, ...(ngDevMode ? [{ debugName: "anchorElementInput", alias: 'anchorElement' }] : [{
212
+ alias: 'anchorElement',
213
+ }]));
214
+ anchorElement = computed(() => this.anchorElementInput() ?? this.elRef.nativeElement.parentElement, ...(ngDevMode ? [{ debugName: "anchorElement" }] : []));
215
+ zIndex = computed(() => this.level() + 10, ...(ngDevMode ? [{ debugName: "zIndex" }] : []));
216
+ isRootLevel = computed(() => this.level() === 0, ...(ngDevMode ? [{ debugName: "isRootLevel" }] : []));
216
217
  // Bounding box of this excluding any extra offset.
217
218
  _box;
218
219
  get box() {
@@ -221,72 +222,69 @@ class RdtMenuOverlayComponent {
221
222
  // Bounding box of parent element.
222
223
  _anchorBox;
223
224
  _containerPadding = { top: 0, bottom: 0 };
224
- // Recalculate child components only after they are initialized.
225
- _viewWasInit = false;
226
225
  // Currently applied vertical and horizontal directions.
227
- verticalDir = null;
228
- horizontalDir = null;
229
- expandedChild = null;
230
- autofocusSubmenuItem = null;
226
+ verticalDir = signal(null, ...(ngDevMode ? [{ debugName: "verticalDir", equal: areVertDirsEqual }] : [{
227
+ equal: areVertDirsEqual,
228
+ }]));
229
+ horizontalDir = signal(null, ...(ngDevMode ? [{ debugName: "horizontalDir", equal: areHorDirsEqual }] : [{
230
+ equal: areHorDirsEqual,
231
+ }]));
232
+ expandedChild = signal(null, ...(ngDevMode ? [{ debugName: "expandedChild" }] : []));
233
+ autofocusSubmenuItem = signal(null, ...(ngDevMode ? [{ debugName: "autofocusSubmenuItem" }] : []));
231
234
  keyActions = {
232
235
  [KB_CODE.ARROW.UP]: (index) => this.focusPrevItem(index),
233
236
  [KB_CODE.ARROW.DOWN]: (index) => this.focusNextItem(index),
234
237
  [KB_CODE.ARROW.RIGHT]: (index) => this.openSubmenu(index, 'first', RdtMenuExpandSource.Shortcut),
235
238
  [KB_CODE.ARROW.LEFT]: () => this.closeSelf(),
236
239
  [KB_CODE.HOME]: () => this.focusItem(0),
237
- [KB_CODE.END]: () => this.focusItem(this.item.items.length - 1),
240
+ [KB_CODE.END]: () => this.focusItem(untracked(this.item).items.length - 1),
238
241
  [KB_CODE.ESCAPE]: () => this.closeSelf(),
239
242
  [KB_CODE.ENTER]: (index) => this.invokeItemClickByIndex(index),
240
243
  [KB_CODE.SPACEBAR]: (index) => this.invokeItemClickByIndex(index),
241
244
  };
242
245
  get selfExpandSrc() {
243
- if (this.expanded) {
246
+ if (this.expanded()) {
244
247
  if (this.parentMenu) {
245
- return this.parentMenu.expandedChild?.src;
248
+ return this.parentMenu.expandedChild()?.src;
246
249
  }
247
250
  else {
248
- return this.topLevelMenu.expandedChild?.src;
251
+ return this.topLevelMenu.expandedChild()?.src;
249
252
  }
250
253
  }
251
254
  return undefined;
252
255
  }
253
- ngOnInit() {
254
- this.setClasses();
255
- this.listenTabKeyPress();
256
- }
257
- ngOnChanges(changes) {
258
- const recalcTriggers = [
259
- 'preferredHorizontalDir',
260
- 'preferredVerticalDir',
261
- 'expanded',
262
- ];
263
- if (recalcTriggers.some((key) => key in changes) && this._viewWasInit) {
264
- this.recalculatePosition(this.preferredHorizontalDir, this.preferredVerticalDir);
265
- }
266
- if (!this.expanded) {
267
- this.expandedChild = null;
268
- }
269
- if ('expanded' in changes && this.expanded) {
270
- // Wait for Angular to set .expanded class,
271
- // because invisible elements cannot be focused.
272
- setTimeout(() => {
273
- switch (this.autofocusItem) {
274
- case null:
275
- this.focusItem(0, false);
276
- break;
277
- case 'first':
278
- this.focusItem(0, true);
279
- break;
280
- case 'last':
281
- this.focusItem(this.item.items.length - 1, true);
282
- }
283
- });
256
+ recalcEffect = effect(() => {
257
+ this.recalculatePosition(this.preferredHorizontalDir(), this.preferredVerticalDir());
258
+ }, ...(ngDevMode ? [{ debugName: "recalcEffect" }] : []));
259
+ expandedEffect = effect(() => {
260
+ if (!this.expanded()) {
261
+ this.expandedChild.set(null);
262
+ }
263
+ }, ...(ngDevMode ? [{ debugName: "expandedEffect" }] : []));
264
+ expandedFocusEffect = afterRenderEffect(() => {
265
+ const rootItem = untracked(this.item);
266
+ this.expandedInput();
267
+ const expanded = untracked(this.expanded);
268
+ const autofocusItem = untracked(this.autofocusItem);
269
+ if (expanded) {
270
+ switch (autofocusItem) {
271
+ case null:
272
+ this.focusItem(0, false);
273
+ break;
274
+ case 'first':
275
+ this.focusItem(0, true);
276
+ break;
277
+ case 'last':
278
+ this.focusItem(rootItem.items.length - 1, true);
279
+ }
284
280
  }
285
- }
286
- ngAfterViewInit() {
287
- this.measureContainerPadding();
288
- this.recalculatePosition(this.preferredHorizontalDir, this.preferredVerticalDir);
289
- this._viewWasInit = true;
281
+ });
282
+ constructor() {
283
+ afterNextRender(() => {
284
+ this.measureContainerPadding();
285
+ this.recalculatePosition(this.preferredHorizontalDir(), this.preferredVerticalDir());
286
+ this.listenTabKeyPress();
287
+ });
290
288
  }
291
289
  getMinOffsetLeft() {
292
290
  return this.topLevelMenu.bodyMargin.left;
@@ -305,9 +303,11 @@ class RdtMenuOverlayComponent {
305
303
  this.topLevelMenu.bodyMargin.bottom);
306
304
  }
307
305
  recalculatePosition(preferredHorizontalDir, preferredVerticalDir) {
308
- // Make menu invisible so the menu does not move around in case of slow computer.
306
+ const isRoot = untracked(this.isRootLevel);
307
+ const horizontalDir = untracked(this.horizontalDir);
308
+ const verticalDir = untracked(this.verticalDir);
309
309
  this.measureBoundingRect();
310
- if (!this._box || !this._anchorBox) {
310
+ if (!this._box || !this._anchorBox || !this.topLevelMenu.clientSize) {
311
311
  return;
312
312
  }
313
313
  const newHorDir = this.getRealHorizontalDir(preferredHorizontalDir);
@@ -315,13 +315,13 @@ class RdtMenuOverlayComponent {
315
315
  // Horizontal direction
316
316
  if (newHorDir.dir === 'right') {
317
317
  newHorDir.left += this._anchorBox.left;
318
- if (!this.isRootLevel) {
318
+ if (!isRoot) {
319
319
  newHorDir.left += this._anchorBox.width;
320
320
  }
321
321
  }
322
322
  else if (newHorDir.dir === 'left') {
323
323
  newHorDir.left += this._anchorBox.left - this._box.width;
324
- if (this.isRootLevel) {
324
+ if (isRoot) {
325
325
  newHorDir.left += this._anchorBox.width;
326
326
  }
327
327
  }
@@ -330,7 +330,7 @@ class RdtMenuOverlayComponent {
330
330
  // Vertical direction
331
331
  if (newVertDir.dir === 'down') {
332
332
  newVertDir.top = this._anchorBox.top;
333
- if (this.isRootLevel) {
333
+ if (isRoot) {
334
334
  newVertDir.top += this._anchorBox.height;
335
335
  }
336
336
  else {
@@ -339,45 +339,54 @@ class RdtMenuOverlayComponent {
339
339
  }
340
340
  else if (newVertDir.dir === 'up') {
341
341
  newVertDir.top = this._anchorBox.top - this._box.height;
342
- if (!this.isRootLevel) {
342
+ if (!isRoot) {
343
343
  newVertDir.top += this._anchorBox.height + this._containerPadding.top;
344
344
  }
345
345
  }
346
346
  // Restrictions from header and footer
347
347
  newVertDir.top = Math.min(Math.max(this.getMinOffsetTop(), newVertDir.top), this.getMaxOffsetTop());
348
- if (!areHorDirsEqual(this.horizontalDir, newHorDir) ||
349
- !areVertDirsEqual(this.verticalDir, newVertDir)) {
350
- this.horizontalDir = newHorDir;
351
- this.verticalDir = newVertDir;
348
+ if (!areHorDirsEqual(horizontalDir, newHorDir) ||
349
+ !areVertDirsEqual(verticalDir, newVertDir)) {
350
+ this.horizontalDir.set(newHorDir);
351
+ this.verticalDir.set(newVertDir);
352
352
  this.setClasses();
353
353
  this.measureBoundingRect();
354
354
  }
355
355
  this.recalculateChildren();
356
356
  }
357
+ recalculateChildren() {
358
+ const horizontalDir = untracked(this.horizontalDir);
359
+ const verticalDir = untracked(this.verticalDir);
360
+ if (this.children && horizontalDir && verticalDir) {
361
+ this.children.forEach((child) => child.recalculatePosition(horizontalDir.dir, verticalDir.dir));
362
+ }
363
+ }
357
364
  onItemPointerEnter(item) {
358
- if (this.topLevelMenu.openOnHover &&
359
- this.expandedChild?.src !== RdtMenuExpandSource.Click) {
360
- this.autofocusSubmenuItem = null;
365
+ const expandedChild = untracked(this.expandedChild);
366
+ const openOnHover = untracked(this.topLevelMenu.openOnHover);
367
+ if (openOnHover && expandedChild?.src !== RdtMenuExpandSource.Click) {
368
+ this.autofocusSubmenuItem.set(null);
361
369
  if (menuItemHasChildren(item)) {
362
- this.expandedChild = { item, src: RdtMenuExpandSource.Hover };
363
- this.expanded = true;
370
+ this.expandedChild.set({ item, src: RdtMenuExpandSource.Hover });
371
+ this.expanded.set(true);
364
372
  }
365
373
  else {
366
374
  //console.log('expanded child', this.expandedChild);
367
- this.expandedChild = null;
375
+ this.expandedChild.set(null);
368
376
  }
369
377
  }
370
378
  }
371
379
  onItemClick(item) {
380
+ const expandedChild = untracked(this.expandedChild);
372
381
  const hasChildren = menuItemHasChildren(item);
373
- if ((hasChildren && this.expandedChild?.item !== item) ||
374
- (this.topLevelMenu.openOnHover &&
375
- this.expandedChild?.src === RdtMenuExpandSource.Hover)) {
376
- this.autofocusSubmenuItem = null;
377
- this.expandedChild = { item, src: RdtMenuExpandSource.Click };
382
+ const openOnHover = this.topLevelMenu.openOnHover();
383
+ if ((hasChildren && expandedChild?.item !== item) ||
384
+ (openOnHover && expandedChild?.src === RdtMenuExpandSource.Hover)) {
385
+ this.autofocusSubmenuItem.set(null);
386
+ this.expandedChild.set({ item, src: RdtMenuExpandSource.Click });
378
387
  }
379
388
  else {
380
- this.expandedChild = null;
389
+ this.expandedChild.set(null);
381
390
  }
382
391
  // Could also listen to router events, but might be triggered by
383
392
  // child router navigation.
@@ -393,23 +402,24 @@ class RdtMenuOverlayComponent {
393
402
  this.router.navigate(item.routerLink);
394
403
  }
395
404
  this.onItemClick(item);
396
- this.autofocusSubmenuItem = 'first';
405
+ this.autofocusSubmenuItem.set('first');
397
406
  }
398
407
  getChildRoutes(item) {
399
408
  return this.topLevelMenu.getChildRoutes(item);
400
409
  }
401
410
  closeSubmenus(focusExpanded = false) {
402
- if (focusExpanded && this.expandedChild) {
403
- this.focusItem(this.expandedChild.item);
411
+ const expandedChild = this.expandedChild();
412
+ if (focusExpanded && expandedChild) {
413
+ this.focusItem(expandedChild.item);
404
414
  }
405
- this.expandedChild = null;
415
+ this.expandedChild.set(null);
406
416
  this.cd.markForCheck();
407
417
  }
408
418
  focusItemRecursively(path) {
409
419
  const children = [...path];
410
420
  const thisItem = children.shift();
411
- this.autofocusSubmenuItem = null;
412
- this.autofocusItem = null;
421
+ this.autofocusSubmenuItem.set(null);
422
+ this.autofocusItem.set(null);
413
423
  if (children.length > 0) {
414
424
  this.expandAndGetChild(thisItem, RdtMenuExpandSource.Focus)
415
425
  .pipe(delay(1))
@@ -429,20 +439,22 @@ class RdtMenuOverlayComponent {
429
439
  }
430
440
  }
431
441
  expandAndGetChild(item, src) {
432
- if (this.item.items.indexOf(item) < 0) {
442
+ const rootItem = untracked(this.item);
443
+ if (rootItem.items.indexOf(item) < 0) {
433
444
  throw new Error('Attempting to expand item that is not child item of this.item');
434
445
  }
435
- this.expandedChild = { item, src };
446
+ this.expandedChild.set({ item, src });
436
447
  this.cd.markForCheck();
437
- const child = this.children.find((child) => child.item === item);
448
+ const child = this.children.find((child) => untracked(child.item) === item);
438
449
  if (child) {
439
450
  return of(child);
440
451
  }
441
452
  else {
442
- return this.children.changes.pipe(map(() => this.children.find((child) => child.item === item)), first(RdtObjectUtils.notNullGuard));
453
+ return this.children.changes.pipe(map(() => this.children.find((child) => untracked(child.item) === item)), first(RdtObjectUtils.notNullGuard));
443
454
  }
444
455
  }
445
456
  onKeyDown(itemIndex, event) {
457
+ const rootItem = untracked(this.item);
446
458
  const hasAction = event.code in this.keyActions;
447
459
  const isLetter = RdtStringUtils.isAlphabetCharacter(event.key) ||
448
460
  RdtStringUtils.isNumericCharacter(event.key);
@@ -456,7 +468,7 @@ class RdtMenuOverlayComponent {
456
468
  this.keyActions[event.code](itemIndex);
457
469
  }
458
470
  else if (isLetter) {
459
- const next = findNextItemWithPrefix(this.item.items, itemIndex, event.key);
471
+ const next = findNextItemWithPrefix(rootItem.items, itemIndex, event.key);
460
472
  if (next !== null) {
461
473
  this.focusItem(next);
462
474
  }
@@ -473,7 +485,8 @@ class RdtMenuOverlayComponent {
473
485
  }, 1);
474
486
  }
475
487
  invokeItemClickByIndex(itemIndex) {
476
- const item = this.item.items[itemIndex];
488
+ const rootItem = untracked(this.item);
489
+ const item = rootItem.items[itemIndex];
477
490
  if (!item) {
478
491
  return;
479
492
  }
@@ -485,7 +498,7 @@ class RdtMenuOverlayComponent {
485
498
  itemIndex = item;
486
499
  }
487
500
  else {
488
- itemIndex = this.item.items.indexOf(item);
501
+ itemIndex = this.item().items.indexOf(item);
489
502
  }
490
503
  if (itemIndex >= 0 && itemIndex < this.focusableElements.length) {
491
504
  this.blurAllFocusable();
@@ -505,18 +518,21 @@ class RdtMenuOverlayComponent {
505
518
  }
506
519
  }
507
520
  focusNextItem(itemIndex) {
508
- const next = (itemIndex + 1) % this.item.items.length;
521
+ const rootItem = untracked(this.item);
522
+ const next = (itemIndex + 1) % rootItem.items.length;
509
523
  this.focusItem(next);
510
524
  }
511
525
  focusPrevItem(itemIndex) {
512
- const prev = (itemIndex - 1 + this.item.items.length) % this.item.items.length;
526
+ const rootItem = untracked(this.item);
527
+ const prev = (itemIndex - 1 + rootItem.items.length) % rootItem.items.length;
513
528
  this.focusItem(prev);
514
529
  }
515
530
  openSubmenu(itemIndex, visibleFocus, src) {
516
- if (itemIndex < this.item.items.length &&
517
- menuItemHasChildren(this.item.items[itemIndex])) {
518
- this.expandedChild = { item: this.item.items[itemIndex], src };
519
- this.autofocusSubmenuItem = visibleFocus;
531
+ const rootItem = untracked(this.item);
532
+ if (itemIndex < rootItem.items.length &&
533
+ menuItemHasChildren(rootItem.items[itemIndex])) {
534
+ this.expandedChild.set({ item: rootItem.items[itemIndex], src });
535
+ this.autofocusSubmenuItem.set(visibleFocus);
520
536
  }
521
537
  }
522
538
  closeSelf(focusExpanded = true) {
@@ -528,21 +544,23 @@ class RdtMenuOverlayComponent {
528
544
  }
529
545
  }
530
546
  checkActiveElement(event) {
531
- if (this.topLevelMenu.closeOnFocusOut && !this.topLevelMenu.openOnHover) {
547
+ const closeOnFocusOut = untracked(this.topLevelMenu.closeOnFocusOut);
548
+ if (closeOnFocusOut && !this.topLevelMenu.openOnHover) {
532
549
  const thisEl = this.elRef.nativeElement;
533
550
  const target = event.relatedTarget;
534
551
  if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
535
- this.expandedChild = null;
552
+ this.expandedChild.set(null);
536
553
  }
537
554
  }
538
555
  }
539
556
  // Calculates direction of this menu and offset in case
540
557
  // menu won't fit in left nor right of parent menu.
541
558
  getRealHorizontalDir(preferredHorizontalDir) {
559
+ const isRoot = untracked(this.isRootLevel);
542
560
  let left;
543
561
  let right;
544
562
  // This menu is directly under menubar
545
- if (this.level === 0) {
563
+ if (isRoot) {
546
564
  left = this._anchorBox.right - this._box.width;
547
565
  right =
548
566
  this.topLevelMenu.clientSize.width -
@@ -602,9 +620,10 @@ class RdtMenuOverlayComponent {
602
620
  }
603
621
  }
604
622
  getRealVerticalDir(preferredVerticalDir) {
623
+ const isRoot = untracked(this.isRootLevel);
605
624
  let bottom;
606
625
  let top;
607
- if (this.level === 0) {
626
+ if (isRoot) {
608
627
  bottom =
609
628
  this.topLevelMenu.clientSize.height +
610
629
  this._anchorBox.bottom -
@@ -647,7 +666,7 @@ class RdtMenuOverlayComponent {
647
666
  // Should always be called after parent menu has already been measured.
648
667
  measureBoundingRect() {
649
668
  this._box = this.elRef.nativeElement.getBoundingClientRect();
650
- const anchor = this.anchorElement ?? this.elRef.nativeElement.parentElement;
669
+ const anchor = this.anchorElement();
651
670
  this._anchorBox = anchor.getBoundingClientRect();
652
671
  }
653
672
  measureContainerPadding() {
@@ -656,14 +675,12 @@ class RdtMenuOverlayComponent {
656
675
  const paddingBottom = parseFloat(computedStyles.paddingBottom);
657
676
  this._containerPadding = { top: paddingTop, bottom: paddingBottom };
658
677
  }
659
- recalculateChildren() {
660
- if (this.expanded && this.horizontalDir && this.verticalDir) {
661
- this.children.forEach((child) => child.recalculatePosition(this.horizontalDir.dir, this.verticalDir.dir));
662
- }
663
- }
664
678
  setClasses() {
665
- if (this.verticalDir) {
666
- if (this.verticalDir.dir === 'up') {
679
+ const isRoot = this.isRootLevel();
680
+ const vertical = this.verticalDir();
681
+ const horizontal = this.horizontalDir();
682
+ if (vertical) {
683
+ if (vertical.dir === 'up') {
667
684
  this.setClass('rdt-overlay-up');
668
685
  this.removeClass('rdt-overlay-down');
669
686
  }
@@ -671,10 +688,10 @@ class RdtMenuOverlayComponent {
671
688
  this.removeClass('rdt-overlay-up');
672
689
  this.setClass('rdt-overlay-down');
673
690
  }
674
- this.setOffset('top', this.verticalDir.top);
691
+ this.setOffset('top', vertical.top);
675
692
  }
676
- if (this.horizontalDir) {
677
- if (this.horizontalDir.dir === 'left') {
693
+ if (horizontal) {
694
+ if (horizontal.dir === 'left') {
678
695
  this.setClass('rdt-overlay-left');
679
696
  this.removeClass('rdt-overlay-right');
680
697
  }
@@ -682,9 +699,9 @@ class RdtMenuOverlayComponent {
682
699
  this.removeClass('rdt-overlay-left');
683
700
  this.setClass('rdt-overlay-right');
684
701
  }
685
- this.setOffset('left', this.horizontalDir.left);
702
+ this.setOffset('left', horizontal.left);
686
703
  }
687
- if (this.isRootLevel) {
704
+ if (isRoot) {
688
705
  this.setClass('rdt-menu-root');
689
706
  this.removeClass('rdt-menu-sub');
690
707
  }
@@ -713,13 +730,18 @@ class RdtMenuOverlayComponent {
713
730
  .pipe(takeUntilDestroyed(this.destroyRef))
714
731
  .subscribe((event) => this.onTabKeyPress(event));
715
732
  }
716
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
717
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: { item: "item", level: "level", preferredHorizontalDir: "preferredHorizontalDir", preferredVerticalDir: "preferredVerticalDir", expanded: "expanded", autofocusItem: "autofocusItem", anchorElement: "anchorElement" }, host: { listeners: { "window:focusout": "checkActiveElement($event)" }, properties: { "class.expanded": "this.expanded", "attr.role": "this.roleAttr", "attr.tabindex": "this.tabindexAttr", "style.z-index": "this.zIndex" } }, viewQueries: [{ propertyName: "menuItemContainer", first: true, predicate: ["menuItemContainer"], descendants: true }, { propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n <li\r\n *ngFor=\"let item of item.items; let i = index\"\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n <ng-container *ngIf=\"!item.routerLink && !item.externalLink\">\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n <span\r\n class=\"menu-item-icon rdt-menu-icon-right\"\r\n *ngIf=\"item.items\"\r\n ></span>\r\n </div>\r\n </button>\r\n </ng-container>\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n <ng-container *ngIf=\"item.routerLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"item.externalLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n <rdt-menu-overlay\r\n *ngIf=\"item.items && expanded\"\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"horizontalDir?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir?.dir!\"\r\n [level]=\"level + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n </li>\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
733
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuOverlayComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
734
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: RdtMenuOverlayComponent, isStandalone: false, selector: "rdt-menu-overlay", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: true, transformFunction: null }, preferredHorizontalDir: { classPropertyName: "preferredHorizontalDir", publicName: "preferredHorizontalDir", isSignal: true, isRequired: false, transformFunction: null }, preferredVerticalDir: { classPropertyName: "preferredVerticalDir", publicName: "preferredVerticalDir", isSignal: true, isRequired: false, transformFunction: null }, expandedInput: { classPropertyName: "expandedInput", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null }, autofocusItemInput: { classPropertyName: "autofocusItemInput", publicName: "autofocusItem", isSignal: true, isRequired: false, transformFunction: null }, anchorElementInput: { classPropertyName: "anchorElementInput", publicName: "anchorElement", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "tabindex": "-1", "role": "menu" }, listeners: { "window:focusout": "checkActiveElement($event)" }, properties: { "class.expanded": "expanded()", "style.z-index": "zIndex()" } }, viewQueries: [{ propertyName: "menuItemContainer", first: true, predicate: ["menuItemContainer"], descendants: true }, { propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], ngImport: i0, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n @for(item of item().items; track item; let i = $index) {\r\n <li\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if (item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n @if (item.items) {\r\n <span class=\"menu-item-icon rdt-menu-icon-right\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if (item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n }\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n @if (item.items && expanded()) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem()\"\r\n [preferredHorizontalDir]=\"horizontalDir()?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir()?.dir!\"\r\n [level]=\"level() + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);font-size:var(--rdt-menu-item-font-size);font-weight:var(--rdt-menu-item-font-weight);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
718
735
  }
719
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuOverlayComponent, decorators: [{
736
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuOverlayComponent, decorators: [{
720
737
  type: Component,
721
- args: [{ selector: 'rdt-menu-overlay', changeDetection: ChangeDetectionStrategy.OnPush, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n <li\r\n *ngFor=\"let item of item.items; let i = index\"\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n <ng-container *ngIf=\"!item.routerLink && !item.externalLink\">\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n <span\r\n class=\"menu-item-icon rdt-menu-icon-right\"\r\n *ngIf=\"item.items\"\r\n ></span>\r\n </div>\r\n </button>\r\n </ng-container>\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n <span *ngIf=\"item.shortcut\" class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n <ng-container *ngIf=\"item.routerLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <ng-container *ngIf=\"item.externalLink\">\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n </ng-container>\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n <rdt-menu-overlay\r\n *ngIf=\"item.items && expanded\"\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"horizontalDir?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir?.dir!\"\r\n [level]=\"level + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n </li>\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"] }]
722
- }], propDecorators: { children: [{
738
+ args: [{ selector: 'rdt-menu-overlay', changeDetection: ChangeDetectionStrategy.OnPush, standalone: false, host: {
739
+ '[class.expanded]': 'expanded()',
740
+ '[style.z-index]': 'zIndex()',
741
+ tabindex: '-1',
742
+ role: 'menu',
743
+ }, template: "<ul class=\"menu-item-container\" role=\"presentation\" #menuItemContainer>\r\n @for(item of item().items; track item; let i = $index) {\r\n <li\r\n role=\"presentation\"\r\n class=\"menu-item\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n rdtAnyRouteActive=\"menu-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if (item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"chevron_right\"\r\n class=\"menu-item-icon\"\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n -->\r\n @if (item.items) {\r\n <span class=\"menu-item-icon rdt-menu-icon-right\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO:\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-item-icon\"\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if (item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [queryParams]=\"item.queryParams\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n }\r\n\r\n <!-- Child menus exist only if this menu is expanded. -->\r\n <!-- Only one invisible level is always attached to DOM, the rest does not exist. -->\r\n @if (item.items && expanded()) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem()\"\r\n [preferredHorizontalDir]=\"horizontalDir()?.dir!\"\r\n [preferredVerticalDir]=\"verticalDir()?.dir!\"\r\n [level]=\"level() + 1\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: [":host{visibility:hidden;position:fixed;min-width:var(--rdt-menu-min-width);box-shadow:var(--rdt-menu-box-shadow);border-radius:var(--rdt-menu-border-radius);overflow-x:hidden;overflow-y:auto;max-height:calc(100vh - var(--rdt-menu-margin-top, 0px) - var(--rdt-menu-margin-bottom, 0px))}:host.expanded{visibility:visible}ul.menu-item-container{list-style-type:none;padding:var(--rdt-menu-padding-horizontal-padding) 0;border-radius:var(--rdt-menu-border-radius);background-color:var(--rdt-menu-background);margin-top:0;margin-bottom:0;margin-block-start:0;margin-block-end:0}.menu-item-content{cursor:pointer;display:flex;align-items:center;width:100%;padding:var(--rdt-menu-item-padding);background-color:var(--rdt-menu-item-background);color:var(--rdt-menu-item-text-color);font-size:var(--rdt-menu-item-font-size);font-weight:var(--rdt-menu-item-font-weight);border:var(--rdt-menu-item-border);outline:var(--rdt-menu-item-outline)}.menu-item{display:flex;position:relative;box-sizing:border-box}.menu-item.menu-item-route-active>.menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-route-active-background);--rdt-menu-item-text-color: var(--rdt-menu-item-route-active-text-color);--rdt-menu-item-border: var(--rdt-menu-item-route-active-border);--rdt-menu-item-outline: var(--rdt-menu-item-route-active-outline)}.menu-item .menu-item-content:hover{--rdt-menu-item-background: var(--rdt-menu-item-hover-background);--rdt-menu-item-text-color: var(--rdt-menu-item-hover-text-color);--rdt-menu-item-border: var(--rdt-menu-item-hover-border);--rdt-menu-item-outline: var(--rdt-menu-item-hover-outline)}.menu-item [aria-expanded=true].menu-item-content{--rdt-menu-item-background: var(--rdt-menu-item-expanded-background);--rdt-menu-item-text-color: var(--rdt-menu-item-expanded-text-color);--rdt-menu-item-border: var(--rdt-menu-item-expanded-border);--rdt-menu-item-outline: var(--rdt-menu-item-expanded-outline)}.menu-item .menu-item-content.focus-visible:focus,.menu-item .menu-item-content:focus-visible{--rdt-menu-item-background: var(--rdt-menu-item-focus-background);--rdt-menu-item-text-color: var(--rdt-menu-item-focus-text-color);--rdt-menu-item-border: var(--rdt-menu-item-focus-border);--rdt-menu-item-outline: var(--rdt-menu-item-focus-outline)}.menu-item-icon.rdt-menu-icon-right{width:0;height:0;border-top:var(--rdt-menu-default-icon-size) solid transparent;border-bottom:var(--rdt-menu-default-icon-size) solid transparent;border-left:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-item-text-color)}\n"] }]
744
+ }], ctorParameters: () => [], propDecorators: { children: [{
723
745
  type: ViewChildren,
724
746
  args: [RdtMenuOverlayComponent]
725
747
  }], focusableElements: [{
@@ -728,48 +750,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImpor
728
750
  }], menuItemContainer: [{
729
751
  type: ViewChild,
730
752
  args: ['menuItemContainer']
731
- }], item: [{
732
- type: Input
733
- }], level: [{
734
- type: Input
735
- }], preferredHorizontalDir: [{
736
- type: Input
737
- }], preferredVerticalDir: [{
738
- type: Input
739
- }], expanded: [{
740
- type: HostBinding,
741
- args: ['class.expanded']
742
- }, {
743
- type: Input
744
- }], autofocusItem: [{
745
- type: Input
746
- }], anchorElement: [{
747
- type: Input
748
- }], roleAttr: [{
749
- type: HostBinding,
750
- args: ['attr.role']
751
- }], tabindexAttr: [{
752
- type: HostBinding,
753
- args: ['attr.tabindex']
754
- }], zIndex: [{
755
- type: HostBinding,
756
- args: ['style.z-index']
757
753
  }], checkActiveElement: [{
758
754
  type: HostListener,
759
755
  args: ['window:focusout', ['$event']]
760
756
  }] } });
761
757
 
762
758
  class RdtMenuBaseComponent {
763
- preferredVerticalDir = DEFAULT_MENU_VERTICAL_DIR;
764
- preferredHorizontalDir = DEFAULT_MENU_HORIZONTAL_DIR;
759
+ preferredVerticalDir = input(DEFAULT_MENU_VERTICAL_DIR, ...(ngDevMode ? [{ debugName: "preferredVerticalDir" }] : []));
760
+ preferredHorizontalDir = input(DEFAULT_MENU_HORIZONTAL_DIR, ...(ngDevMode ? [{ debugName: "preferredHorizontalDir" }] : []));
765
761
  // Mode only matters if item has shortcut and only children, no command nor routerLink
766
762
  // FOCUS_ITEM will put focus on item with shortcut
767
763
  // OPEN_SUBMENU will open its submenu and put focus on the first item in it
768
764
  // If item has command or routerLink, it will always be activated and everything closed
769
- shortcutMode = RdtMenuShortcutMode.OPEN_SUBMENU;
770
- closeOnFocusOut = false;
771
- openOnHover = false;
772
- hitboxMargin = 10;
765
+ shortcutMode = input(RdtMenuShortcutMode.OPEN_SUBMENU, ...(ngDevMode ? [{ debugName: "shortcutMode" }] : []));
766
+ closeOnFocusOut = input(false, ...(ngDevMode ? [{ debugName: "closeOnFocusOut", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
767
+ openOnHover = input(false, ...(ngDevMode ? [{ debugName: "openOnHover", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
768
+ hitboxMargin = input(10, ...(ngDevMode ? [{ debugName: "hitboxMargin", transform: numberAttribute }] : [{ transform: numberAttribute }]));
773
769
  cd = inject(ChangeDetectorRef);
774
770
  destroyRef = inject(DestroyRef);
775
771
  rdtRouter = inject(RdtRouterService);
@@ -781,10 +777,19 @@ class RdtMenuBaseComponent {
781
777
  injector = inject(EnvironmentInjector);
782
778
  children;
783
779
  focusableElements;
784
- classes = 'rdt-menu-base';
785
- expandedChild = null;
780
+ expandedChild = signal(null, ...(ngDevMode ? [{ debugName: "expandedChild" }] : []));
786
781
  autofocusSubmenuItem = null;
787
- parsedItems;
782
+ filteredItems = computed(() => {
783
+ this.navigationEnd();
784
+ const items = this.allParsedItems();
785
+ const current = this.rdtRouter.parseAbsoluteUrl();
786
+ if (!current) {
787
+ return items;
788
+ }
789
+ else {
790
+ return this.filterRec(items, current);
791
+ }
792
+ }, ...(ngDevMode ? [{ debugName: "filteredItems" }] : []));
788
793
  get clientSize() {
789
794
  return this._clientSize;
790
795
  }
@@ -797,78 +802,74 @@ class RdtMenuBaseComponent {
797
802
  return this._buttonContainerRect;
798
803
  }
799
804
  _buttonContainerRect;
800
- allParsedItems;
801
- childRoutesMap = new Map();
802
- shortcutSub = new Subscription();
803
- shortcutMap = {};
805
+ childRoutesMap = computed(() => getChildRoutesMap(this.filteredItems()), ...(ngDevMode ? [{ debugName: "childRoutesMap" }] : []));
804
806
  keyActions = {
805
807
  [KB_CODE.ARROW.LEFT]: (index) => this.focusPrevItem(index),
806
808
  [KB_CODE.ARROW.RIGHT]: (index) => this.focusNextItem(index),
807
809
  [KB_CODE.ARROW.DOWN]: (index) => this.openSubmenu(index, 'first', RdtMenuExpandSource.Shortcut),
808
810
  [KB_CODE.ARROW.UP]: (index) => this.openSubmenu(index, 'last', RdtMenuExpandSource.Shortcut),
809
811
  [KB_CODE.HOME]: () => this.focusItem(0),
810
- [KB_CODE.END]: () => this.focusItem(this.parsedItems.length - 1),
812
+ [KB_CODE.END]: () => this.focusItem(untracked(this.filteredItems).length - 1),
811
813
  [KB_CODE.ENTER]: (index) => this.invokeItemClickByIndex(index),
812
814
  [KB_CODE.SPACEBAR]: (index) => this.invokeItemClickByIndex(index),
813
815
  };
816
+ navigationEnd = toSignal(this.rdtRouter.navigationEnd$);
814
817
  // Returns all routes asociated with item or its subitems.
815
818
  getChildRoutes(item) {
816
- return this.childRoutesMap.get(item) ?? [];
819
+ return this.childRoutesMap().get(item) ?? [];
817
820
  }
818
- ngOnInit() {
819
- this.rdtRouter.navigationEnd$
820
- .pipe(takeUntilDestroyed(this.destroyRef))
821
- .subscribe((ev) => this.filterItems());
822
- this.measure();
823
- }
824
- ngOnChanges(changes) {
825
- if (this.children) {
826
- this.recalculateChildren();
827
- }
828
- }
829
- ngAfterViewInit() {
830
- this.listenWindowResize();
831
- // Not using timeout results in horizontal overflow on html element
832
- setTimeout(() => {
821
+ constructor() {
822
+ this.listenShortcuts();
823
+ afterNextRender(() => {
824
+ this.listenWindowResize();
833
825
  this.measure();
834
826
  this.recalculateChildren();
835
- }, 50);
827
+ });
836
828
  }
829
+ recalcChildrenEffect = effect(() => {
830
+ this.recalculateChildren();
831
+ }, ...(ngDevMode ? [{ debugName: "recalcChildrenEffect" }] : []));
837
832
  recalculateChildren() {
838
- this.children.forEach((child) => {
839
- child.recalculatePosition(this.preferredHorizontalDir, this.preferredVerticalDir);
840
- });
833
+ if (this.children) {
834
+ this.children.forEach((child) => {
835
+ child.recalculatePosition(this.preferredHorizontalDir(), this.preferredVerticalDir());
836
+ });
837
+ }
841
838
  }
842
839
  closeSubmenus(focusExpanded = false) {
843
- if (focusExpanded && this.expandedChild) {
844
- this.focusItem(this.expandedChild.item);
840
+ const expandedChild = untracked(this.expandedChild);
841
+ if (focusExpanded && expandedChild) {
842
+ this.focusItem(expandedChild.item);
845
843
  }
846
- this.expandedChild = null;
844
+ this.expandedChild.set(null);
847
845
  this.cd.markForCheck();
848
846
  }
849
847
  onItemClick(item) {
850
- if ((menuItemHasChildren(item) && this.expandedChild?.item !== item) ||
851
- (this.openOnHover &&
852
- this.expandedChild?.src === RdtMenuExpandSource.Hover)) {
848
+ const expandedChild = untracked(this.expandedChild);
849
+ const openOnHover = untracked(this.openOnHover);
850
+ if ((menuItemHasChildren(item) && expandedChild?.item !== item) ||
851
+ (openOnHover && expandedChild?.src === RdtMenuExpandSource.Hover)) {
853
852
  this.autofocusSubmenuItem = null;
854
- this.expandedChild = { item, src: RdtMenuExpandSource.Click };
853
+ this.expandedChild.set({ item, src: RdtMenuExpandSource.Click });
855
854
  }
856
855
  else {
857
- this.expandedChild = null;
856
+ this.expandedChild.set(null);
858
857
  }
859
858
  if (typeof item.command === 'function') {
860
859
  item.command();
861
860
  }
862
861
  }
863
862
  onItemPointerEnter(item) {
864
- if (this.openOnHover) {
863
+ const expandedChild = untracked(this.expandedChild);
864
+ const openOnHover = untracked(this.openOnHover);
865
+ if (openOnHover) {
865
866
  if (menuItemHasChildren(item) &&
866
- this.expandedChild?.src !== RdtMenuExpandSource.Click) {
867
+ expandedChild?.src !== RdtMenuExpandSource.Click) {
867
868
  this.autofocusSubmenuItem = null;
868
- this.expandedChild = { item, src: RdtMenuExpandSource.Hover };
869
+ this.expandedChild.set({ item, src: RdtMenuExpandSource.Hover });
869
870
  }
870
871
  else {
871
- this.expandedChild = null;
872
+ this.expandedChild.set(null);
872
873
  }
873
874
  }
874
875
  }
@@ -886,7 +887,8 @@ class RdtMenuBaseComponent {
886
887
  this.keyActions[event.code](itemIndex);
887
888
  }
888
889
  else if (isLetter) {
889
- const next = findNextItemWithPrefix(this.parsedItems, itemIndex, event.key);
890
+ const filteredItems = untracked(this.filteredItems);
891
+ const next = findNextItemWithPrefix(filteredItems, itemIndex, event.key);
890
892
  if (next !== null) {
891
893
  this.focusItem(next);
892
894
  }
@@ -899,18 +901,6 @@ class RdtMenuBaseComponent {
899
901
  this.onItemClick(item);
900
902
  this.autofocusSubmenuItem = 'first';
901
903
  }
902
- filterItems() {
903
- const current = this.rdtRouter.parseAbsoluteUrl();
904
- if (!current) {
905
- this.parsedItems = this.allParsedItems;
906
- }
907
- else {
908
- this.parsedItems = this.filterRec(this.allParsedItems, current);
909
- }
910
- this.childRoutesMap = getChildRoutesMap(this.parsedItems);
911
- this.listenShortcuts();
912
- this.cd.markForCheck();
913
- }
914
904
  filterRec(items, current) {
915
905
  let currentParent = current.route;
916
906
  const currentParams = current.params;
@@ -952,27 +942,30 @@ class RdtMenuBaseComponent {
952
942
  });
953
943
  }
954
944
  invokeItemClickByIndex(itemIndex) {
955
- const item = this.parsedItems[itemIndex];
945
+ const filteredItems = untracked(this.filteredItems);
946
+ const item = filteredItems[itemIndex];
956
947
  if (!item) {
957
948
  return;
958
949
  }
959
950
  this.invokeItemClick(item);
960
951
  }
961
952
  openSubmenu(itemIndex, visibleFocus, src) {
962
- if (itemIndex < this.parsedItems.length &&
963
- menuItemHasChildren(this.parsedItems[itemIndex])) {
964
- const item = this.parsedItems[itemIndex];
953
+ const filteredItems = untracked(this.filteredItems);
954
+ if (itemIndex < filteredItems.length &&
955
+ menuItemHasChildren(filteredItems[itemIndex])) {
956
+ const item = filteredItems[itemIndex];
965
957
  this.autofocusSubmenuItem = visibleFocus;
966
- this.expandedChild = { item, src };
958
+ this.expandedChild.set({ item, src });
967
959
  }
968
960
  }
969
961
  focusItem(item) {
962
+ const filteredItems = untracked(this.filteredItems);
970
963
  let itemIndex;
971
964
  if (typeof item === 'number') {
972
965
  itemIndex = item;
973
966
  }
974
967
  else {
975
- itemIndex = this.parsedItems.indexOf(item);
968
+ itemIndex = filteredItems.indexOf(item);
976
969
  }
977
970
  if (itemIndex >= 0 && itemIndex < this.focusableElements.length) {
978
971
  this.blurAllFocusable();
@@ -980,11 +973,13 @@ class RdtMenuBaseComponent {
980
973
  }
981
974
  }
982
975
  focusNextItem(itemIndex) {
983
- const next = (itemIndex + 1) % this.parsedItems.length;
976
+ const filteredItems = untracked(this.filteredItems);
977
+ const next = (itemIndex + 1) % filteredItems.length;
984
978
  this.focusItem(next);
985
979
  }
986
980
  focusPrevItem(itemIndex) {
987
- const prev = (itemIndex - 1 + this.parsedItems.length) % this.parsedItems.length;
981
+ const filteredItems = untracked(this.filteredItems);
982
+ const prev = (itemIndex - 1 + filteredItems.length) % filteredItems.length;
988
983
  this.focusItem(prev);
989
984
  }
990
985
  blurAllFocusable() {
@@ -998,7 +993,9 @@ class RdtMenuBaseComponent {
998
993
  }
999
994
  }
1000
995
  onPointerMove(event) {
1001
- if (this.openOnHover && this.expandedChild) {
996
+ const expandedChild = untracked(this.expandedChild);
997
+ const openOnHover = untracked(this.openOnHover);
998
+ if (openOnHover && expandedChild) {
1002
999
  const hitboxes = this.getHitboxes();
1003
1000
  const isInside = hitboxes.some((hitbox) => this.isPointerInsideHitbox(hitbox.rect, event));
1004
1001
  for (let i = hitboxes.length - 1; i >= 0; i--) {
@@ -1012,12 +1009,13 @@ class RdtMenuBaseComponent {
1012
1009
  }
1013
1010
  // Closes menu if user navigates outside it using Tab.
1014
1011
  checkActiveElement(event) {
1015
- if (this.closeOnFocusOut && !this.openOnHover) {
1012
+ const closeOnFocusOut = untracked(this.closeOnFocusOut);
1013
+ if (closeOnFocusOut && !this.openOnHover) {
1016
1014
  console.log('focusout', event);
1017
1015
  const thisEl = this.elRef.nativeElement;
1018
1016
  const target = event.relatedTarget;
1019
1017
  if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
1020
- this.expandedChild = null;
1018
+ this.expandedChild.set(null);
1021
1019
  }
1022
1020
  }
1023
1021
  }
@@ -1070,14 +1068,13 @@ class RdtMenuBaseComponent {
1070
1068
  });
1071
1069
  }
1072
1070
  listenShortcuts() {
1073
- const itemsWithShortcuts = getMenuItemsShortcuts(this.parsedItems);
1074
- const shortcuts = itemsWithShortcuts.map((it) => it.shortcut);
1075
- this.shortcutMap = this.getShortcutMap(itemsWithShortcuts);
1076
- this.shortcutSub.unsubscribe();
1077
- this.shortcutSub = this.shortcutService
1078
- .listen(shortcuts)
1079
- .pipe(takeUntilDestroyed(this.destroyRef))
1080
- .subscribe((evt) => this.onShortcut(evt.shortcut));
1071
+ const filteredItems$ = toObservable(this.filteredItems);
1072
+ const itemsWithShortcuts$ = filteredItems$.pipe(map(getMenuItemsShortcuts));
1073
+ const shortcuts$ = itemsWithShortcuts$.pipe(map((items) => items.map((it) => it.shortcut)));
1074
+ const map$ = itemsWithShortcuts$.pipe(map((items) => this.getShortcutMap(items)));
1075
+ shortcuts$
1076
+ .pipe(switchMap((shortcuts) => this.shortcutService.listen(shortcuts)), withLatestFrom(map$), takeUntilDestroyed(this.destroyRef))
1077
+ .subscribe(([evt, map]) => this.onShortcut(evt.shortcut, map));
1081
1078
  }
1082
1079
  getShortcutMap(itemsWithShortcuts) {
1083
1080
  const shortcutMap = {};
@@ -1086,10 +1083,10 @@ class RdtMenuBaseComponent {
1086
1083
  });
1087
1084
  return shortcutMap;
1088
1085
  }
1089
- onShortcut(shortcut) {
1090
- const path = this.shortcutMap[shortcut.hotkeysValue];
1086
+ onShortcut(shortcut, map) {
1087
+ const path = map[shortcut.hotkeysValue];
1091
1088
  if (!path) {
1092
- console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`, this.shortcutMap);
1089
+ console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`, map);
1093
1090
  }
1094
1091
  const last = path[path.length - 1];
1095
1092
  const hasRoute = menuItemHasRoute(last);
@@ -1108,8 +1105,9 @@ class RdtMenuBaseComponent {
1108
1105
  }
1109
1106
  }
1110
1107
  activateItemRecursively(path, src) {
1108
+ const shortcutMode = untracked(this.shortcutMode);
1111
1109
  const children = [...path];
1112
- if (this.shortcutMode === RdtMenuShortcutMode.OPEN_SUBMENU) {
1110
+ if (shortcutMode === RdtMenuShortcutMode.OPEN_SUBMENU) {
1113
1111
  const last = children[children.length - 1];
1114
1112
  if (menuItemHasChildren(last) && last.items[0]) {
1115
1113
  children.push(last.items[0]);
@@ -1117,12 +1115,12 @@ class RdtMenuBaseComponent {
1117
1115
  }
1118
1116
  const thisItem = children.shift();
1119
1117
  if (children.length > 0) {
1120
- this.expandedChild = { item: thisItem, src };
1121
- const overlay = this.children.find((child) => child.item === thisItem);
1118
+ this.expandedChild.set({ item: thisItem, src });
1119
+ const overlay = this.children.find((child) => untracked(child.item) === thisItem);
1122
1120
  overlay.focusItemRecursively(children);
1123
1121
  }
1124
1122
  else {
1125
- this.expandedChild = null;
1123
+ this.expandedChild.set(null);
1126
1124
  this.focusItem(thisItem);
1127
1125
  }
1128
1126
  }
@@ -1130,10 +1128,11 @@ class RdtMenuBaseComponent {
1130
1128
  const rect = hitbox;
1131
1129
  const x = event.clientX;
1132
1130
  const y = event.clientY;
1133
- return (x >= rect.left - this.hitboxMargin &&
1134
- x <= rect.right + this.hitboxMargin &&
1135
- y >= rect.top - this.hitboxMargin &&
1136
- y <= rect.bottom + this.hitboxMargin);
1131
+ const margin = untracked(this.hitboxMargin);
1132
+ return (x >= rect.left - margin &&
1133
+ x <= rect.right + margin &&
1134
+ y >= rect.top - margin &&
1135
+ y <= rect.bottom + margin);
1137
1136
  }
1138
1137
  getHitboxes() {
1139
1138
  const boxes = this.getOpenMenuBoundingBoxes();
@@ -1151,7 +1150,7 @@ class RdtMenuBaseComponent {
1151
1150
  return boxes;
1152
1151
  }
1153
1152
  getOpenMenuBoundingBoxesRec(overlay, boxes) {
1154
- if (overlay.expanded) {
1153
+ if (overlay.expanded()) {
1155
1154
  let someByClick = false;
1156
1155
  overlay.children.forEach((child) => (someByClick ||= this.getOpenMenuBoundingBoxesRec(child, boxes)));
1157
1156
  const fixed = someByClick || overlay.selfExpandSrc === RdtMenuExpandSource.Click;
@@ -1164,44 +1163,25 @@ class RdtMenuBaseComponent {
1164
1163
  }
1165
1164
  return false;
1166
1165
  }
1167
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1168
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "18.2.7", type: RdtMenuBaseComponent, inputs: { preferredVerticalDir: "preferredVerticalDir", preferredHorizontalDir: "preferredHorizontalDir", shortcutMode: "shortcutMode", closeOnFocusOut: ["closeOnFocusOut", "closeOnFocusOut", booleanAttribute], openOnHover: ["openOnHover", "openOnHover", booleanAttribute], hitboxMargin: ["hitboxMargin", "hitboxMargin", numberAttribute] }, host: { listeners: { "window:pointermove": "onPointerMove($event)", "window:focusout": "checkActiveElement($event)", "document:click": "onDocumentClick($event)" }, properties: { "class": "this.classes" } }, viewQueries: [{ propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], usesOnChanges: true, ngImport: i0 });
1166
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1167
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.7", type: RdtMenuBaseComponent, isStandalone: true, inputs: { preferredVerticalDir: { classPropertyName: "preferredVerticalDir", publicName: "preferredVerticalDir", isSignal: true, isRequired: false, transformFunction: null }, preferredHorizontalDir: { classPropertyName: "preferredHorizontalDir", publicName: "preferredHorizontalDir", isSignal: true, isRequired: false, transformFunction: null }, shortcutMode: { classPropertyName: "shortcutMode", publicName: "shortcutMode", isSignal: true, isRequired: false, transformFunction: null }, closeOnFocusOut: { classPropertyName: "closeOnFocusOut", publicName: "closeOnFocusOut", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", isSignal: true, isRequired: false, transformFunction: null }, hitboxMargin: { classPropertyName: "hitboxMargin", publicName: "hitboxMargin", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "window:pointermove": "onPointerMove($event)", "document:click": "onDocumentClick($event)", "window:focusout": "checkActiveElement($event)" }, classAttribute: "rdt-menu-base" }, viewQueries: [{ propertyName: "children", predicate: RdtMenuOverlayComponent, descendants: true }, { propertyName: "focusableElements", predicate: ["focusableItem"], descendants: true }], ngImport: i0 });
1169
1168
  }
1170
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuBaseComponent, decorators: [{
1171
- type: Directive
1172
- }], propDecorators: { preferredVerticalDir: [{
1173
- type: Input
1174
- }], preferredHorizontalDir: [{
1175
- type: Input
1176
- }], shortcutMode: [{
1177
- type: Input
1178
- }], closeOnFocusOut: [{
1179
- type: Input,
1180
- args: [{ transform: booleanAttribute }]
1181
- }], openOnHover: [{
1182
- type: Input,
1183
- args: [{ transform: booleanAttribute }]
1184
- }], hitboxMargin: [{
1185
- type: Input,
1186
- args: [{ transform: numberAttribute }]
1187
- }], children: [{
1169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, decorators: [{
1170
+ type: Directive,
1171
+ args: [{
1172
+ host: {
1173
+ class: 'rdt-menu-base',
1174
+ '(window:pointermove)': 'onPointerMove($event)',
1175
+ '(document:click)': 'onDocumentClick($event)',
1176
+ '(window:focusout)': 'checkActiveElement($event)',
1177
+ },
1178
+ }]
1179
+ }], ctorParameters: () => [], propDecorators: { children: [{
1188
1180
  type: ViewChildren,
1189
1181
  args: [RdtMenuOverlayComponent]
1190
1182
  }], focusableElements: [{
1191
1183
  type: ViewChildren,
1192
1184
  args: ['focusableItem']
1193
- }], classes: [{
1194
- type: HostBinding,
1195
- args: ['class']
1196
- }], onPointerMove: [{
1197
- type: HostListener,
1198
- args: ['window:pointermove', ['$event']]
1199
- }], checkActiveElement: [{
1200
- type: HostListener,
1201
- args: ['window:focusout', ['$event']]
1202
- }], onDocumentClick: [{
1203
- type: HostListener,
1204
- args: ['document:click', ['$event']]
1205
1185
  }] } });
1206
1186
 
1207
1187
  class RdtMenuBarComponent extends RdtMenuBaseComponent {
@@ -1209,149 +1189,136 @@ class RdtMenuBarComponent extends RdtMenuBaseComponent {
1209
1189
  get buttonContainer() {
1210
1190
  return this.buttonContainerRef?.nativeElement;
1211
1191
  }
1212
- get items() {
1213
- return this._items;
1214
- }
1215
- set items(value) {
1216
- this._items = value;
1217
- this.allParsedItems = parseMenuItems(value, this.injector);
1218
- this.filterItems();
1219
- }
1220
- _items;
1221
- headerHeight = 0;
1222
- footerHeight = 0;
1223
- roleAttr = 'menubar';
1224
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1225
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.7", type: RdtMenuBarComponent, selector: "rdt-menu-bar", inputs: { items: "items", headerHeight: ["headerHeight", "headerHeight", numberAttribute], footerHeight: ["footerHeight", "footerHeight", numberAttribute] }, host: { properties: { "attr.role": "this.roleAttr" } }, providers: [
1192
+ items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
1193
+ allParsedItems = computed(() => parseMenuItems(this.items(), this.injector), ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
1194
+ headerHeight = input(0, ...(ngDevMode ? [{ debugName: "headerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
1195
+ footerHeight = input(0, ...(ngDevMode ? [{ debugName: "footerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
1196
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1197
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: RdtMenuBarComponent, isStandalone: false, selector: "rdt-menu-bar", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, headerHeight: { classPropertyName: "headerHeight", publicName: "headerHeight", isSignal: true, isRequired: false, transformFunction: null }, footerHeight: { classPropertyName: "footerHeight", publicName: "footerHeight", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menubar" } }, providers: [
1226
1198
  {
1227
1199
  provide: RdtMenuBaseComponent,
1228
1200
  useExisting: RdtMenuBarComponent,
1229
1201
  },
1230
- ], viewQueries: [{ propertyName: "buttonContainerRef", first: true, predicate: ["buttonContainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of parsedItems; track item; let i = $index) {\r\n <li\r\n class=\"menu-bar-item\"\r\n role=\"presentation\"\r\n rdtAnyRouteActive=\"menu-bar-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"expand_more\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n -->\r\n @if(item.items) {\r\n <span class=\"menu-bar-item-icon rdt-menu-icon-down\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!--\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if(item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [target]=\"item.target!\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if(item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.items) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir\"\r\n [preferredVerticalDir]=\"preferredVerticalDir\"\r\n [level]=\"0\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu-bar{-webkit-user-select:none;user-select:none;pointer-events:none;padding:var(--rdt-menu-bar-padding)}.menu-bar-item-container{display:flex;list-style-type:none;margin-bottom:0;margin-top:0;margin-block-start:0;margin-block-end:0;padding-left:0}.menu-bar-item{pointer-events:all;margin:var(--rdt-menu-bar-item-margin);position:relative;display:flex;align-items:center;justify-content:center}.menu-bar-item.menu-bar-item-route-active .menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-route-active-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-route-active-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-route-active-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-route-active-outline)}.menu-bar-item [aria-expanded=true].menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-expanded-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-expanded-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-expanded-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-expanded-outline)}.menu-bar-item-content{cursor:pointer;display:flex;align-items:center;overflow:hidden;padding:var(--rdt-menu-bar-item-padding);border-radius:var(--rdt-menu-bar-item-border-radius);border:var(--rdt-menu-bar-item-border);background-color:var(--rdt-menu-bar-item-background);color:var(--rdt-menu-bar-item-text-color);outline:var(--rdt-menu-bar-item-outline);font-size:inherit}.menu-bar-item-content:hover{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-hover-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-hover-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-hover-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-hover-outline)}.menu-bar-item .menu-bar-item-content.focus-visible:focus,.menu-bar-item .menu-bar-item-content:focus-visible{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-focus-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-focus-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-focus-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-focus-outline)}.menu-bar-item-icon.rdt-menu-icon-down{width:0;height:0;border-left:var(--rdt-menu-default-icon-size) solid transparent;border-right:var(--rdt-menu-default-icon-size) solid transparent;border-top:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-bar-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1202
+ ], viewQueries: [{ propertyName: "buttonContainerRef", first: true, predicate: ["buttonContainer"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of filteredItems(); track item; let i = $index) {\r\n <li\r\n class=\"menu-bar-item\"\r\n role=\"presentation\"\r\n rdtAnyRouteActive=\"menu-bar-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"expand_more\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n -->\r\n @if(item.items) {\r\n <span class=\"menu-bar-item-icon rdt-menu-icon-down\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!--\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if(item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [target]=\"item.target!\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if(item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.items) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu-bar{-webkit-user-select:none;user-select:none;pointer-events:none;padding:var(--rdt-menu-bar-padding)}.menu-bar-item-container{display:flex;list-style-type:none;margin-bottom:0;margin-top:0;margin-block-start:0;margin-block-end:0;padding-left:0}.menu-bar-item{pointer-events:all;margin:var(--rdt-menu-bar-item-margin);position:relative;display:flex;align-items:center;justify-content:center}.menu-bar-item.menu-bar-item-route-active .menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-route-active-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-route-active-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-route-active-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-route-active-outline)}.menu-bar-item [aria-expanded=true].menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-expanded-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-expanded-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-expanded-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-expanded-outline)}.menu-bar-item-content{cursor:pointer;display:flex;align-items:center;overflow:hidden;padding:var(--rdt-menu-bar-item-padding);border-radius:var(--rdt-menu-bar-item-border-radius);border:var(--rdt-menu-bar-item-border);background-color:var(--rdt-menu-bar-item-background);color:var(--rdt-menu-bar-item-text-color);font-weight:var(--rdt-menu-bar-item-font-weight);font-size:var(--rdt-menu-bar-item-font-size, inherit);outline:var(--rdt-menu-bar-item-outline)}.menu-bar-item-content:hover{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-hover-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-hover-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-hover-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-hover-outline)}.menu-bar-item .menu-bar-item-content.focus-visible:focus,.menu-bar-item .menu-bar-item-content:focus-visible{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-focus-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-focus-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-focus-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-focus-outline)}.menu-bar-item-icon.rdt-menu-icon-down{width:0;height:0;border-left:var(--rdt-menu-default-icon-size) solid transparent;border-right:var(--rdt-menu-default-icon-size) solid transparent;border-top:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-bar-item-text-color)}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i3.RdtAnyRouteActiveDirective, selector: "[rdtAnyRouteActive]", inputs: ["rdtAnyRouteActive", "watchedRoutes", "anyRouteActiveOptions", "ariaCurrentWhenActive"] }, { kind: "directive", type: i4.RdtKeyListenerDirective, selector: "[rdtKeyListener]", outputs: ["rdtKeyListener"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1231
1203
  }
1232
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuBarComponent, decorators: [{
1204
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, decorators: [{
1233
1205
  type: Component,
1234
1206
  args: [{ selector: 'rdt-menu-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1235
1207
  {
1236
1208
  provide: RdtMenuBaseComponent,
1237
1209
  useExisting: RdtMenuBarComponent,
1238
1210
  },
1239
- ], template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of parsedItems; track item; let i = $index) {\r\n <li\r\n class=\"menu-bar-item\"\r\n role=\"presentation\"\r\n rdtAnyRouteActive=\"menu-bar-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"expand_more\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n -->\r\n @if(item.items) {\r\n <span class=\"menu-bar-item-icon rdt-menu-icon-down\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!--\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if(item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [target]=\"item.target!\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if(item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.items) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir\"\r\n [preferredVerticalDir]=\"preferredVerticalDir\"\r\n [level]=\"0\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu-bar{-webkit-user-select:none;user-select:none;pointer-events:none;padding:var(--rdt-menu-bar-padding)}.menu-bar-item-container{display:flex;list-style-type:none;margin-bottom:0;margin-top:0;margin-block-start:0;margin-block-end:0;padding-left:0}.menu-bar-item{pointer-events:all;margin:var(--rdt-menu-bar-item-margin);position:relative;display:flex;align-items:center;justify-content:center}.menu-bar-item.menu-bar-item-route-active .menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-route-active-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-route-active-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-route-active-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-route-active-outline)}.menu-bar-item [aria-expanded=true].menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-expanded-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-expanded-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-expanded-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-expanded-outline)}.menu-bar-item-content{cursor:pointer;display:flex;align-items:center;overflow:hidden;padding:var(--rdt-menu-bar-item-padding);border-radius:var(--rdt-menu-bar-item-border-radius);border:var(--rdt-menu-bar-item-border);background-color:var(--rdt-menu-bar-item-background);color:var(--rdt-menu-bar-item-text-color);outline:var(--rdt-menu-bar-item-outline);font-size:inherit}.menu-bar-item-content:hover{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-hover-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-hover-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-hover-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-hover-outline)}.menu-bar-item .menu-bar-item-content.focus-visible:focus,.menu-bar-item .menu-bar-item-content:focus-visible{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-focus-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-focus-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-focus-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-focus-outline)}.menu-bar-item-icon.rdt-menu-icon-down{width:0;height:0;border-left:var(--rdt-menu-default-icon-size) solid transparent;border-right:var(--rdt-menu-default-icon-size) solid transparent;border-top:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-bar-item-text-color)}\n"] }]
1211
+ ], standalone: false, host: {
1212
+ role: 'menubar',
1213
+ }, template: "<ul class=\"menu-bar-item-container\" role=\"presentation\" #buttonContainer>\r\n @for(item of filteredItems(); track item; let i = $index) {\r\n <li\r\n class=\"menu-bar-item\"\r\n role=\"presentation\"\r\n rdtAnyRouteActive=\"menu-bar-item-route-active\"\r\n [watchedRoutes]=\"getChildRoutes(item)\"\r\n (rdtKeyListener)=\"onKeyDown(i, $event)\"\r\n #anchorEl\r\n >\r\n @if(!item.routerLink && !item.externalLink) {\r\n <button\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n (pointerenter)=\"onItemPointerEnter(item)\"\r\n [attr.aria-haspopup]=\"item.items ? 'menu' : null\"\r\n [attr.aria-expanded]=\"item === expandedChild()?.item\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!-- TODO\r\n <rdt-icon\r\n *ngIf=\"item.items\"\r\n name=\"expand_more\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n -->\r\n @if(item.items) {\r\n <span class=\"menu-bar-item-icon rdt-menu-icon-down\"></span>\r\n }\r\n </div>\r\n </button>\r\n }\r\n\r\n <ng-template #linkBody let-item>\r\n {{ item.label }}\r\n\r\n <div class=\"menu-bar-item-right-content\">\r\n @if(item.shortcut) {\r\n <span class=\"menu-item-shortcut\">\r\n {{ item.shortcut.label }}\r\n </span>\r\n }\r\n <!--\r\n <rdt-icon\r\n *ngIf=\"item.icon\"\r\n [name]=\"item.icon\"\r\n class=\"menu-bar-item-icon\"\r\n inverted\r\n />\r\n --></div>\r\n </ng-template>\r\n\r\n @if(item.routerLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [routerLink]=\"item.routerLink\"\r\n [target]=\"item.target!\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if(item.externalLink) {\r\n <a\r\n #focusableItem\r\n class=\"menu-bar-item-content\"\r\n role=\"menuitem\"\r\n (click)=\"onItemClick(item)\"\r\n [href]=\"item.externalLink\"\r\n [target]=\"item.target\"\r\n [attr.tabindex]=\"0\"\r\n [attr.data-testid]=\"item.dataTestId\"\r\n >\r\n <ng-container\r\n *ngTemplateOutlet=\"linkBody; context: { $implicit: item }\"\r\n />\r\n </a>\r\n } @if (item.items) {\r\n <rdt-menu-overlay\r\n [item]=\"$any(item)\"\r\n [expanded]=\"item === expandedChild()?.item\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n [anchorElement]=\"anchorEl\"\r\n />\r\n }\r\n </li>\r\n }\r\n</ul>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu-bar{-webkit-user-select:none;user-select:none;pointer-events:none;padding:var(--rdt-menu-bar-padding)}.menu-bar-item-container{display:flex;list-style-type:none;margin-bottom:0;margin-top:0;margin-block-start:0;margin-block-end:0;padding-left:0}.menu-bar-item{pointer-events:all;margin:var(--rdt-menu-bar-item-margin);position:relative;display:flex;align-items:center;justify-content:center}.menu-bar-item.menu-bar-item-route-active .menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-route-active-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-route-active-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-route-active-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-route-active-outline)}.menu-bar-item [aria-expanded=true].menu-bar-item-content{--rdt-menu-bar-item-background: var( --rdt-menu-bar-item-expanded-background );--rdt-menu-bar-item-text-color: var( --rdt-menu-bar-item-expanded-text-color );--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-expanded-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-expanded-outline)}.menu-bar-item-content{cursor:pointer;display:flex;align-items:center;overflow:hidden;padding:var(--rdt-menu-bar-item-padding);border-radius:var(--rdt-menu-bar-item-border-radius);border:var(--rdt-menu-bar-item-border);background-color:var(--rdt-menu-bar-item-background);color:var(--rdt-menu-bar-item-text-color);font-weight:var(--rdt-menu-bar-item-font-weight);font-size:var(--rdt-menu-bar-item-font-size, inherit);outline:var(--rdt-menu-bar-item-outline)}.menu-bar-item-content:hover{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-hover-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-hover-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-hover-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-hover-outline)}.menu-bar-item .menu-bar-item-content.focus-visible:focus,.menu-bar-item .menu-bar-item-content:focus-visible{--rdt-menu-bar-item-background: var(--rdt-menu-bar-item-focus-background);--rdt-menu-bar-item-text-color: var(--rdt-menu-bar-item-focus-text-color);--rdt-menu-bar-item-border: var(--rdt-menu-bar-item-focus-border);--rdt-menu-bar-item-outline: var(--rdt-menu-bar-item-focus-outline)}.menu-bar-item-icon.rdt-menu-icon-down{width:0;height:0;border-left:var(--rdt-menu-default-icon-size) solid transparent;border-right:var(--rdt-menu-default-icon-size) solid transparent;border-top:var(--rdt-menu-default-icon-size) solid var(--rdt-menu-bar-item-text-color)}\n"] }]
1240
1214
  }], propDecorators: { buttonContainerRef: [{
1241
1215
  type: ViewChild,
1242
1216
  args: ['buttonContainer', { static: true }]
1243
- }], items: [{
1244
- type: Input
1245
- }], headerHeight: [{
1246
- type: Input,
1247
- args: [{ transform: numberAttribute }]
1248
- }], footerHeight: [{
1249
- type: Input,
1250
- args: [{ transform: numberAttribute }]
1251
- }], roleAttr: [{
1252
- type: HostBinding,
1253
- args: ['attr.role']
1254
1217
  }] } });
1255
1218
 
1256
1219
  class RdtMenuComponent extends RdtMenuBaseComponent {
1257
1220
  buttonClass = inject(RDT_BUTTON_BASE_PROVIDER);
1258
- trigger;
1259
- dataTestId = '';
1260
- get items() {
1261
- return this._items;
1262
- }
1263
- set items(value) {
1264
- this._items = value;
1221
+ trigger = input.required(...(ngDevMode ? [{ debugName: "trigger" }] : []));
1222
+ dataTestId = input('', ...(ngDevMode ? [{ debugName: "dataTestId" }] : []));
1223
+ items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
1224
+ allParsedItems = computed(() => {
1225
+ const items = this.items();
1265
1226
  const wrapper = {
1266
1227
  label: '',
1267
1228
  icon: '',
1268
- items: value,
1229
+ items: items,
1269
1230
  };
1270
- this.allParsedItems = parseMenuItems([wrapper], this.injector);
1271
- this.filterItems();
1272
- }
1273
- _items;
1231
+ return parseMenuItems([wrapper], this.injector);
1232
+ }, ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
1274
1233
  focusableElements = new QueryList();
1275
1234
  get buttonContainer() {
1276
- return this.anchorElement ?? undefined;
1235
+ return this.anchorElement() ?? undefined;
1277
1236
  }
1278
1237
  get parsedItem() {
1279
- return this.parsedItems[0];
1238
+ return this.filteredItems()[0];
1280
1239
  }
1281
1240
  get anchorElement() {
1282
- return this.trigger.anchorElement;
1241
+ return this.trigger().anchorElement;
1283
1242
  }
1284
- ngOnInit() {
1285
- super.ngOnInit();
1286
- this.trigger.tabIndex = 0;
1287
- this.trigger.dataTestId = this.dataTestId;
1288
- this.trigger.click$.subscribe(() => this.toggle());
1289
- this.listenPointerOver();
1290
- if (this.anchorElement) {
1291
- console.log('Anchor element:', this.anchorElement);
1292
- this.focusableElements.reset([{ nativeElement: this.anchorElement }]);
1293
- }
1294
- }
1295
- ngDoCheck() {
1296
- if (this.trigger) {
1297
- this.trigger.aria = {
1298
- role: 'menuitem',
1299
- 'aria-haspopup': 'true',
1300
- 'aria-expanded': this.expandedChild?.item === this.parsedItem,
1301
- };
1302
- }
1243
+ constructor() {
1244
+ super();
1245
+ afterNextRender(() => {
1246
+ this.listenPointerOver();
1247
+ this.updateFocusableElements();
1248
+ });
1249
+ this.subscribeClicks();
1250
+ }
1251
+ triggerTabIndexEffect = effect(() => {
1252
+ const trigger = this.trigger();
1253
+ trigger.tabIndex.set(0);
1254
+ }, ...(ngDevMode ? [{ debugName: "triggerTabIndexEffect" }] : []));
1255
+ triggerDataTestIdEffect = effect(() => {
1256
+ const trigger = this.trigger();
1257
+ const dataTestId = this.dataTestId();
1258
+ trigger.dataTestId.set(dataTestId);
1259
+ }, ...(ngDevMode ? [{ debugName: "triggerDataTestIdEffect" }] : []));
1260
+ triggerAriaEffect = effect(() => {
1261
+ const trigger = this.trigger();
1262
+ const expandedChild = this.expandedChild();
1263
+ trigger.aria.set({
1264
+ role: 'menuitem',
1265
+ 'aria-haspopup': 'true',
1266
+ 'aria-expanded': expandedChild?.item === this.parsedItem,
1267
+ });
1268
+ }, ...(ngDevMode ? [{ debugName: "triggerAriaEffect" }] : []));
1269
+ subscribeClicks() {
1270
+ toObservable(this.trigger)
1271
+ .pipe(switchMap((trigger) => trigger.click$), takeUntilDestroyed(this.destroyRef))
1272
+ .subscribe(() => this.toggle());
1303
1273
  }
1304
1274
  toggle() {
1305
1275
  this.onItemClick(this.parsedItem);
1306
- this.cd.markForCheck();
1307
1276
  }
1308
1277
  listenPointerOver() {
1309
- const target = this.anchorElement;
1278
+ const target = this.anchorElement();
1310
1279
  const listener = this.renderer.listen(target, 'pointerover', (event) => {
1311
1280
  this.onItemPointerEnter(this.parsedItem);
1312
1281
  this.cd.markForCheck();
1313
1282
  });
1314
1283
  this.destroyRef.onDestroy(() => listener());
1315
1284
  }
1316
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1317
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.7", type: RdtMenuComponent, selector: "rdt-menu", inputs: { trigger: "trigger", dataTestId: "dataTestId", items: "items" }, providers: [
1285
+ updateFocusableElements() {
1286
+ const anchor = this.anchorElement();
1287
+ if (anchor) {
1288
+ this.focusableElements.reset([{ nativeElement: anchor }]);
1289
+ }
1290
+ }
1291
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1292
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.7", type: RdtMenuComponent, isStandalone: false, selector: "rdt-menu", inputs: { trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: true, transformFunction: null }, dataTestId: { classPropertyName: "dataTestId", publicName: "dataTestId", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null } }, providers: [
1318
1293
  {
1319
1294
  provide: RdtMenuBaseComponent,
1320
1295
  useExisting: RdtMenuComponent,
1321
1296
  },
1322
- ], usesInheritance: true, ngImport: i0, template: "<rdt-menu-overlay\r\n *ngIf=\"parsedItem\"\r\n [anchorElement]=\"anchorElement!\"\r\n [item]=\"$any(parsedItem)\"\r\n [expanded]=\"expandedChild?.item === parsedItem\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir\"\r\n [preferredVerticalDir]=\"preferredVerticalDir\"\r\n [level]=\"0\"\r\n/>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu{display:block;position:relative}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1297
+ ], usesInheritance: true, ngImport: i0, template: "@if (parsedItem) {\r\n<rdt-menu-overlay\r\n [anchorElement]=\"anchorElement()\"\r\n [item]=\"$any(parsedItem)\"\r\n [expanded]=\"expandedChild()?.item === parsedItem\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n/>\r\n}\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu{display:block;position:relative}\n"], dependencies: [{ kind: "component", type: RdtMenuOverlayComponent, selector: "rdt-menu-overlay", inputs: ["item", "level", "preferredHorizontalDir", "preferredVerticalDir", "expanded", "autofocusItem", "anchorElement"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
1323
1298
  }
1324
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuComponent, decorators: [{
1299
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, decorators: [{
1325
1300
  type: Component,
1326
1301
  args: [{ selector: 'rdt-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1327
1302
  {
1328
1303
  provide: RdtMenuBaseComponent,
1329
1304
  useExisting: RdtMenuComponent,
1330
1305
  },
1331
- ], template: "<rdt-menu-overlay\r\n *ngIf=\"parsedItem\"\r\n [anchorElement]=\"anchorElement!\"\r\n [item]=\"$any(parsedItem)\"\r\n [expanded]=\"expandedChild?.item === parsedItem\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir\"\r\n [preferredVerticalDir]=\"preferredVerticalDir\"\r\n [level]=\"0\"\r\n/>\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu{display:block;position:relative}\n"] }]
1332
- }], propDecorators: { trigger: [{
1333
- type: Input,
1334
- args: [{ required: true }]
1335
- }], dataTestId: [{
1336
- type: Input
1337
- }], items: [{
1338
- type: Input,
1339
- args: [{ required: true }]
1340
- }] } });
1306
+ ], standalone: false, template: "@if (parsedItem) {\r\n<rdt-menu-overlay\r\n [anchorElement]=\"anchorElement()\"\r\n [item]=\"$any(parsedItem)\"\r\n [expanded]=\"expandedChild()?.item === parsedItem\"\r\n [autofocusItem]=\"autofocusSubmenuItem\"\r\n [preferredHorizontalDir]=\"preferredHorizontalDir()\"\r\n [preferredVerticalDir]=\"preferredVerticalDir()\"\r\n [level]=\"0\"\r\n/>\r\n}\r\n", styles: ["a.menu-bar-item-content,a.menu-item-content,button.menu-bar-item-content,button.menu-item-content{white-space:nowrap;appearance:none;text-decoration:none;box-sizing:border-box}.menu-item-right-content,.menu-bar-item-right-content{margin-left:auto;display:flex;align-items:center}.menu-item-shortcut,.menu-bar-item-shortcut{margin-left:2rem}.menu-item-icon,.menu-bar-item-icon{margin-left:.5rem;font-size:1.2rem}.dp3-menu-base ul{margin-bottom:0}.rdt-menu-root{margin-left:0}.rdt-menu-root.rdt-overlay-down{margin-top:var(--rdt-menu-overlay-margin-y)}.rdt-menu-root.rdt-overlay-up{margin-top:calc(-1 * var(--rdt-menu-overlay-margin-y))}.rdt-menu-sub.rdt-overlay-left{margin-left:calc(-1 * var(--rdt-menu-overlay-margin-x))}.rdt-menu-sub.rdt-overlay-right{margin-left:var(--rdt-menu-overlay-margin-x)}rdt-menu{display:block;position:relative}\n"] }]
1307
+ }], ctorParameters: () => [] });
1341
1308
 
1342
1309
  class RdtMenuModule {
1343
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1344
- static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuModule, declarations: [RdtMenuOverlayComponent,
1310
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1311
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, declarations: [RdtMenuOverlayComponent,
1345
1312
  RdtMenuComponent,
1346
1313
  RdtMenuBarComponent], imports: [CommonModule,
1347
1314
  RouterModule,
1348
1315
  RdtAnyRouteActiveDirective,
1349
1316
  RdtKeyListenerDirective,
1350
1317
  RdtButtonOutletDirective], exports: [RdtMenuComponent, RdtMenuBarComponent] });
1351
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuModule, imports: [CommonModule,
1318
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, imports: [CommonModule,
1352
1319
  RouterModule] });
1353
1320
  }
1354
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuModule, decorators: [{
1321
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, decorators: [{
1355
1322
  type: NgModule,
1356
1323
  args: [{
1357
1324
  imports: [