@ngrdt/menu 0.0.17 → 0.0.19

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);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.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);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"] }]
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,12 @@ 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) {
1016
- console.log('focusout', event);
1012
+ const closeOnFocusOut = untracked(this.closeOnFocusOut);
1013
+ if (closeOnFocusOut && !this.openOnHover) {
1017
1014
  const thisEl = this.elRef.nativeElement;
1018
1015
  const target = event.relatedTarget;
1019
1016
  if (!(target instanceof HTMLElement) || !thisEl.contains(target)) {
1020
- this.expandedChild = null;
1017
+ this.expandedChild.set(null);
1021
1018
  }
1022
1019
  }
1023
1020
  }
@@ -1070,14 +1067,13 @@ class RdtMenuBaseComponent {
1070
1067
  });
1071
1068
  }
1072
1069
  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));
1070
+ const filteredItems$ = toObservable(this.filteredItems);
1071
+ const itemsWithShortcuts$ = filteredItems$.pipe(map(getMenuItemsShortcuts));
1072
+ const shortcuts$ = itemsWithShortcuts$.pipe(map((items) => items.map((it) => it.shortcut)));
1073
+ const map$ = itemsWithShortcuts$.pipe(map((items) => this.getShortcutMap(items)));
1074
+ shortcuts$
1075
+ .pipe(switchMap((shortcuts) => this.shortcutService.listen(shortcuts)), withLatestFrom(map$), takeUntilDestroyed(this.destroyRef))
1076
+ .subscribe(([evt, map]) => this.onShortcut(evt.shortcut, map));
1081
1077
  }
1082
1078
  getShortcutMap(itemsWithShortcuts) {
1083
1079
  const shortcutMap = {};
@@ -1086,10 +1082,10 @@ class RdtMenuBaseComponent {
1086
1082
  });
1087
1083
  return shortcutMap;
1088
1084
  }
1089
- onShortcut(shortcut) {
1090
- const path = this.shortcutMap[shortcut.hotkeysValue];
1085
+ onShortcut(shortcut, map) {
1086
+ const path = map[shortcut.hotkeysValue];
1091
1087
  if (!path) {
1092
- console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`, this.shortcutMap);
1088
+ console.warn(`Menu shortcut ${shortcut.hotkeysValue} was detected, but there is no path associated with it.`, map);
1093
1089
  }
1094
1090
  const last = path[path.length - 1];
1095
1091
  const hasRoute = menuItemHasRoute(last);
@@ -1108,8 +1104,9 @@ class RdtMenuBaseComponent {
1108
1104
  }
1109
1105
  }
1110
1106
  activateItemRecursively(path, src) {
1107
+ const shortcutMode = untracked(this.shortcutMode);
1111
1108
  const children = [...path];
1112
- if (this.shortcutMode === RdtMenuShortcutMode.OPEN_SUBMENU) {
1109
+ if (shortcutMode === RdtMenuShortcutMode.OPEN_SUBMENU) {
1113
1110
  const last = children[children.length - 1];
1114
1111
  if (menuItemHasChildren(last) && last.items[0]) {
1115
1112
  children.push(last.items[0]);
@@ -1117,12 +1114,12 @@ class RdtMenuBaseComponent {
1117
1114
  }
1118
1115
  const thisItem = children.shift();
1119
1116
  if (children.length > 0) {
1120
- this.expandedChild = { item: thisItem, src };
1121
- const overlay = this.children.find((child) => child.item === thisItem);
1117
+ this.expandedChild.set({ item: thisItem, src });
1118
+ const overlay = this.children.find((child) => untracked(child.item) === thisItem);
1122
1119
  overlay.focusItemRecursively(children);
1123
1120
  }
1124
1121
  else {
1125
- this.expandedChild = null;
1122
+ this.expandedChild.set(null);
1126
1123
  this.focusItem(thisItem);
1127
1124
  }
1128
1125
  }
@@ -1130,10 +1127,11 @@ class RdtMenuBaseComponent {
1130
1127
  const rect = hitbox;
1131
1128
  const x = event.clientX;
1132
1129
  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);
1130
+ const margin = untracked(this.hitboxMargin);
1131
+ return (x >= rect.left - margin &&
1132
+ x <= rect.right + margin &&
1133
+ y >= rect.top - margin &&
1134
+ y <= rect.bottom + margin);
1137
1135
  }
1138
1136
  getHitboxes() {
1139
1137
  const boxes = this.getOpenMenuBoundingBoxes();
@@ -1151,7 +1149,7 @@ class RdtMenuBaseComponent {
1151
1149
  return boxes;
1152
1150
  }
1153
1151
  getOpenMenuBoundingBoxesRec(overlay, boxes) {
1154
- if (overlay.expanded) {
1152
+ if (overlay.expanded()) {
1155
1153
  let someByClick = false;
1156
1154
  overlay.children.forEach((child) => (someByClick ||= this.getOpenMenuBoundingBoxesRec(child, boxes)));
1157
1155
  const fixed = someByClick || overlay.selfExpandSrc === RdtMenuExpandSource.Click;
@@ -1164,44 +1162,25 @@ class RdtMenuBaseComponent {
1164
1162
  }
1165
1163
  return false;
1166
1164
  }
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 });
1165
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1166
+ 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
1167
  }
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: [{
1168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBaseComponent, decorators: [{
1169
+ type: Directive,
1170
+ args: [{
1171
+ host: {
1172
+ class: 'rdt-menu-base',
1173
+ '(window:pointermove)': 'onPointerMove($event)',
1174
+ '(document:click)': 'onDocumentClick($event)',
1175
+ '(window:focusout)': 'checkActiveElement($event)',
1176
+ },
1177
+ }]
1178
+ }], ctorParameters: () => [], propDecorators: { children: [{
1188
1179
  type: ViewChildren,
1189
1180
  args: [RdtMenuOverlayComponent]
1190
1181
  }], focusableElements: [{
1191
1182
  type: ViewChildren,
1192
1183
  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
1184
  }] } });
1206
1185
 
1207
1186
  class RdtMenuBarComponent extends RdtMenuBaseComponent {
@@ -1209,149 +1188,136 @@ class RdtMenuBarComponent extends RdtMenuBaseComponent {
1209
1188
  get buttonContainer() {
1210
1189
  return this.buttonContainerRef?.nativeElement;
1211
1190
  }
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: [
1191
+ items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
1192
+ allParsedItems = computed(() => parseMenuItems(this.items(), this.injector), ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
1193
+ headerHeight = input(0, ...(ngDevMode ? [{ debugName: "headerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
1194
+ footerHeight = input(0, ...(ngDevMode ? [{ debugName: "footerHeight", transform: numberAttribute }] : [{ transform: numberAttribute }]));
1195
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
1196
+ 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
1197
  {
1227
1198
  provide: RdtMenuBaseComponent,
1228
1199
  useExisting: RdtMenuBarComponent,
1229
1200
  },
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);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 });
1201
+ ], 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
1202
  }
1232
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuBarComponent, decorators: [{
1203
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuBarComponent, decorators: [{
1233
1204
  type: Component,
1234
1205
  args: [{ selector: 'rdt-menu-bar', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1235
1206
  {
1236
1207
  provide: RdtMenuBaseComponent,
1237
1208
  useExisting: RdtMenuBarComponent,
1238
1209
  },
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);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"] }]
1210
+ ], standalone: false, host: {
1211
+ role: 'menubar',
1212
+ }, 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
1213
  }], propDecorators: { buttonContainerRef: [{
1241
1214
  type: ViewChild,
1242
1215
  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
1216
  }] } });
1255
1217
 
1256
1218
  class RdtMenuComponent extends RdtMenuBaseComponent {
1257
1219
  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;
1220
+ trigger = input.required(...(ngDevMode ? [{ debugName: "trigger" }] : []));
1221
+ dataTestId = input('', ...(ngDevMode ? [{ debugName: "dataTestId" }] : []));
1222
+ items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
1223
+ allParsedItems = computed(() => {
1224
+ const items = this.items();
1265
1225
  const wrapper = {
1266
1226
  label: '',
1267
1227
  icon: '',
1268
- items: value,
1228
+ items: items,
1269
1229
  };
1270
- this.allParsedItems = parseMenuItems([wrapper], this.injector);
1271
- this.filterItems();
1272
- }
1273
- _items;
1230
+ return parseMenuItems([wrapper], this.injector);
1231
+ }, ...(ngDevMode ? [{ debugName: "allParsedItems" }] : []));
1274
1232
  focusableElements = new QueryList();
1275
1233
  get buttonContainer() {
1276
- return this.anchorElement ?? undefined;
1234
+ return this.anchorElement() ?? undefined;
1277
1235
  }
1278
1236
  get parsedItem() {
1279
- return this.parsedItems[0];
1237
+ return this.filteredItems()[0];
1280
1238
  }
1281
1239
  get anchorElement() {
1282
- return this.trigger.anchorElement;
1240
+ return this.trigger().anchorElement;
1283
1241
  }
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
- }
1242
+ constructor() {
1243
+ super();
1244
+ afterNextRender(() => {
1245
+ this.listenPointerOver();
1246
+ this.updateFocusableElements();
1247
+ });
1248
+ this.subscribeClicks();
1249
+ }
1250
+ triggerTabIndexEffect = effect(() => {
1251
+ const trigger = this.trigger();
1252
+ trigger.tabIndex.set(0);
1253
+ }, ...(ngDevMode ? [{ debugName: "triggerTabIndexEffect" }] : []));
1254
+ triggerDataTestIdEffect = effect(() => {
1255
+ const trigger = this.trigger();
1256
+ const dataTestId = this.dataTestId();
1257
+ trigger.dataTestId.set(dataTestId);
1258
+ }, ...(ngDevMode ? [{ debugName: "triggerDataTestIdEffect" }] : []));
1259
+ triggerAriaEffect = effect(() => {
1260
+ const trigger = this.trigger();
1261
+ const expandedChild = this.expandedChild();
1262
+ trigger.aria.set({
1263
+ role: 'menuitem',
1264
+ 'aria-haspopup': 'true',
1265
+ 'aria-expanded': expandedChild?.item === this.parsedItem,
1266
+ });
1267
+ }, ...(ngDevMode ? [{ debugName: "triggerAriaEffect" }] : []));
1268
+ subscribeClicks() {
1269
+ toObservable(this.trigger)
1270
+ .pipe(switchMap((trigger) => trigger.click$), takeUntilDestroyed(this.destroyRef))
1271
+ .subscribe(() => this.toggle());
1303
1272
  }
1304
1273
  toggle() {
1305
1274
  this.onItemClick(this.parsedItem);
1306
- this.cd.markForCheck();
1307
1275
  }
1308
1276
  listenPointerOver() {
1309
- const target = this.anchorElement;
1277
+ const target = this.anchorElement();
1310
1278
  const listener = this.renderer.listen(target, 'pointerover', (event) => {
1311
1279
  this.onItemPointerEnter(this.parsedItem);
1312
1280
  this.cd.markForCheck();
1313
1281
  });
1314
1282
  this.destroyRef.onDestroy(() => listener());
1315
1283
  }
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: [
1284
+ updateFocusableElements() {
1285
+ const anchor = this.anchorElement();
1286
+ if (anchor) {
1287
+ this.focusableElements.reset([{ nativeElement: anchor }]);
1288
+ }
1289
+ }
1290
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1291
+ 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
1292
  {
1319
1293
  provide: RdtMenuBaseComponent,
1320
1294
  useExisting: RdtMenuComponent,
1321
1295
  },
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 });
1296
+ ], 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
1297
  }
1324
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuComponent, decorators: [{
1298
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuComponent, decorators: [{
1325
1299
  type: Component,
1326
1300
  args: [{ selector: 'rdt-menu', changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [
1327
1301
  {
1328
1302
  provide: RdtMenuBaseComponent,
1329
1303
  useExisting: RdtMenuComponent,
1330
1304
  },
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
- }] } });
1305
+ ], 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"] }]
1306
+ }], ctorParameters: () => [] });
1341
1307
 
1342
1308
  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,
1309
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1310
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, declarations: [RdtMenuOverlayComponent,
1345
1311
  RdtMenuComponent,
1346
1312
  RdtMenuBarComponent], imports: [CommonModule,
1347
1313
  RouterModule,
1348
1314
  RdtAnyRouteActiveDirective,
1349
1315
  RdtKeyListenerDirective,
1350
1316
  RdtButtonOutletDirective], exports: [RdtMenuComponent, RdtMenuBarComponent] });
1351
- static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuModule, imports: [CommonModule,
1317
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, imports: [CommonModule,
1352
1318
  RouterModule] });
1353
1319
  }
1354
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.7", ngImport: i0, type: RdtMenuModule, decorators: [{
1320
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.7", ngImport: i0, type: RdtMenuModule, decorators: [{
1355
1321
  type: NgModule,
1356
1322
  args: [{
1357
1323
  imports: [