@radix-ng/primitives 1.0.1 → 1.0.2

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.
Files changed (37) hide show
  1. package/composite/README.md +1 -1
  2. package/fesm2022/radix-ng-primitives-accordion.mjs +10 -10
  3. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  4. package/fesm2022/radix-ng-primitives-checkbox.mjs +134 -58
  5. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  6. package/fesm2022/radix-ng-primitives-composite.mjs +127 -43
  7. package/fesm2022/radix-ng-primitives-composite.mjs.map +1 -1
  8. package/fesm2022/radix-ng-primitives-menu.mjs +288 -63
  9. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-menubar.mjs +24 -1
  11. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  12. package/fesm2022/radix-ng-primitives-select.mjs +56 -29
  13. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  14. package/fesm2022/radix-ng-primitives-slider.mjs +57 -13
  15. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  16. package/fesm2022/radix-ng-primitives-tabs.mjs +292 -59
  17. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-toolbar.mjs +19 -13
  19. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  20. package/package.json +2 -10
  21. package/types/radix-ng-primitives-accordion.d.ts +4 -4
  22. package/types/radix-ng-primitives-checkbox.d.ts +98 -70
  23. package/types/radix-ng-primitives-composite.d.ts +58 -15
  24. package/types/radix-ng-primitives-menu.d.ts +44 -16
  25. package/types/radix-ng-primitives-menubar.d.ts +2 -0
  26. package/types/radix-ng-primitives-select.d.ts +46 -32
  27. package/types/radix-ng-primitives-slider.d.ts +19 -4
  28. package/types/radix-ng-primitives-tabs.d.ts +63 -11
  29. package/types/radix-ng-primitives-toolbar.d.ts +80 -73
  30. package/collection/README.md +0 -1
  31. package/fesm2022/radix-ng-primitives-collection.mjs +0 -72
  32. package/fesm2022/radix-ng-primitives-collection.mjs.map +0 -1
  33. package/fesm2022/radix-ng-primitives-roving-focus.mjs +0 -420
  34. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +0 -1
  35. package/roving-focus/README.md +0 -3
  36. package/types/radix-ng-primitives-collection.d.ts +0 -44
  37. package/types/radix-ng-primitives-roving-focus.d.ts +0 -201
@@ -7,33 +7,83 @@ import { createContext, createFloatingRootContext, useTransitionStatus, createCa
7
7
  import { injectDirection } from '@radix-ng/primitives/direction-provider';
8
8
  import * as i3 from '@radix-ng/primitives/floating-focus-manager';
9
9
  import { getInteractionTypeFromEvent, RdxFloatingFocusManager, provideFloatingFocusManagerConfig, createRdxTriggerInteraction, useTriggerFocusGuards } from '@radix-ng/primitives/floating-focus-manager';
10
+ import * as i1$1 from '@radix-ng/primitives/composite';
11
+ import { isElementVisible, RdxCompositeListItem, RdxCompositeList } from '@radix-ng/primitives/composite';
10
12
  import { outputFromObservable, outputToObservable } from '@angular/core/rxjs-interop';
11
13
  import { RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
12
14
  import { RdxFocusScope } from '@radix-ng/primitives/focus-scope';
13
- import * as i1$1 from '@radix-ng/primitives/portal';
15
+ import * as i1$2 from '@radix-ng/primitives/portal';
14
16
  import { RdxPortalPresence } from '@radix-ng/primitives/portal';
15
17
  import { provideRdxPresenceContext } from '@radix-ng/primitives/presence';
16
18
  import { isPlatformBrowser } from '@angular/common';
17
- import * as i2$1 from '@radix-ng/primitives/composite';
18
- import { RdxCompositeItem } from '@radix-ng/primitives/composite';
19
19
 
20
- /** Selector for focusable menu items within a popup. */
20
+ /** Selector for menu items within a popup. Disabled items stay focusable to match Base UI. */
21
21
  const RDX_MENU_ITEM_SELECTOR = [
22
- '[rdxMenuItem]:not([data-disabled])',
23
- '[rdxMenuCheckboxItem]:not([data-disabled])',
24
- '[rdxMenuRadioItem]:not([data-disabled])',
25
- '[rdxMenuLinkItem]:not([data-disabled])',
26
- '[rdxMenuSubTrigger]:not([data-disabled])'
22
+ '[rdxMenuItem]',
23
+ '[rdxMenuCheckboxItem]',
24
+ '[rdxMenuRadioItem]',
25
+ '[rdxMenuLinkItem]',
26
+ '[rdxMenuSubTrigger]'
27
27
  ].join(',');
28
28
  function getFocusableMenuItems(popup) {
29
29
  return Array.from(popup.querySelectorAll(RDX_MENU_ITEM_SELECTOR)).filter((item) => item.closest('[rdxMenuPopup]') === popup);
30
30
  }
31
+ function getCompositeMenuItems(list) {
32
+ const map = list.itemMap();
33
+ return list
34
+ .items()
35
+ .map(({ element }) => {
36
+ const metadata = map.get(element);
37
+ if (!metadata || !isElementVisible(element)) {
38
+ return null;
39
+ }
40
+ return {
41
+ element,
42
+ index: metadata.index,
43
+ label: getMenuItemLabel(element, metadata),
44
+ metadata
45
+ };
46
+ })
47
+ .filter((item) => item !== null);
48
+ }
49
+ function getDomMenuItems(popup) {
50
+ return getFocusableMenuItems(popup).map((element, index) => ({
51
+ element,
52
+ index,
53
+ label: getMenuItemLabel(element),
54
+ metadata: {
55
+ index,
56
+ type: getMenuItemType(element),
57
+ disabled: element.hasAttribute('data-disabled'),
58
+ label: element.dataset['label']
59
+ }
60
+ }));
61
+ }
62
+ function getMenuItemLabel(element, metadata) {
63
+ return (metadata?.label ?? element.dataset['label'] ?? element.textContent?.trim() ?? '').toLowerCase();
64
+ }
65
+ function getMenuItemType(element) {
66
+ if (element.hasAttribute('rdxMenuCheckboxItem')) {
67
+ return 'checkbox-item';
68
+ }
69
+ if (element.hasAttribute('rdxMenuRadioItem')) {
70
+ return 'radio-item';
71
+ }
72
+ if (element.hasAttribute('rdxMenuLinkItem')) {
73
+ return 'link-item';
74
+ }
75
+ if (element.hasAttribute('rdxMenuSubTrigger')) {
76
+ return 'submenu-trigger';
77
+ }
78
+ return 'regular-item';
79
+ }
31
80
 
32
81
  const [injectRdxMenuRootContext, provideRdxMenuRootContext] = createContext('RdxMenuRootContext', 'components/menu');
33
82
  function buildContext(instance) {
34
83
  return {
35
84
  isOpen: instance.open,
36
85
  present: instance.present,
86
+ activeIndex: instance.activeIndex.asReadonly(),
37
87
  disabled: instance.effectiveDisabled,
38
88
  modal: instance.effectiveModal,
39
89
  loopFocus: instance.loopFocus,
@@ -55,6 +105,7 @@ function buildContext(instance) {
55
105
  beforeContentFocusGuard: instance.beforeContentFocusGuard.asReadonly(),
56
106
  transitionStatus: instance.transitionStatus,
57
107
  close: (reason, event) => instance.close(reason, event),
108
+ setActiveIndex: (index) => instance.setActiveIndex(index),
58
109
  closeEntireMenu: (reason, event) => instance.closeEntireMenu(reason, event),
59
110
  toggle: (reason, event) => instance.toggle(reason, event),
60
111
  show: (autoFocus, reason, event) => instance.show(autoFocus, reason, event),
@@ -123,6 +174,7 @@ class RdxMenuRoot {
123
174
  this.popupElement = signal(undefined, ...(ngDevMode ? [{ debugName: "popupElement" }] : /* istanbul ignore next */ []));
124
175
  this.beforeContentFocusGuard = signal(null, ...(ngDevMode ? [{ debugName: "beforeContentFocusGuard" }] : /* istanbul ignore next */ []));
125
176
  this.transitionStatus = this.transition.status;
177
+ this.activeIndex = signal(null, ...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
126
178
  /** Whether the popup grabs focus when it opens. Set false for menubar hover-switching. */
127
179
  this.autoFocus = signal('first', ...(ngDevMode ? [{ debugName: "autoFocus" }] : /* istanbul ignore next */ []));
128
180
  this.isSubmenu = signal(false, ...(ngDevMode ? [{ debugName: "isSubmenu" }] : /* istanbul ignore next */ []));
@@ -178,6 +230,11 @@ class RdxMenuRoot {
178
230
  this.preventUnmountOnClose.set(false);
179
231
  }
180
232
  });
233
+ effect(() => {
234
+ if (!this.open()) {
235
+ this.activeIndex.set(null);
236
+ }
237
+ });
181
238
  let previousOpen = this.open();
182
239
  effect(() => {
183
240
  const open = this.open();
@@ -244,6 +301,14 @@ class RdxMenuRoot {
244
301
  markAsContextMenu() {
245
302
  this.isContextMenu.set(true);
246
303
  }
304
+ setActiveIndex(index) {
305
+ if (this.effectiveDisabled() && index !== null) {
306
+ return;
307
+ }
308
+ if (this.activeIndex() !== index) {
309
+ this.activeIndex.set(index);
310
+ }
311
+ }
247
312
  setAllowMouseUpTrigger(value) {
248
313
  if (this.parentRoot) {
249
314
  this.parentRoot.setAllowMouseUpTrigger(value);
@@ -338,6 +403,7 @@ class RdxMenuRoot {
338
403
  return;
339
404
  }
340
405
  if (autoFocus === 'popup') {
406
+ this.setActiveIndex(null);
341
407
  popup.focus({ preventScroll: true });
342
408
  return;
343
409
  }
@@ -448,6 +514,7 @@ const checkboxItemContextFactory = () => {
448
514
  class RdxMenuCheckboxItem {
449
515
  constructor() {
450
516
  this.rootContext = injectRdxMenuRootContext(true);
517
+ this.listItem = inject(RdxCompositeListItem, { self: true });
451
518
  this.elementRef = inject(ElementRef);
452
519
  this.isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
453
520
  /** Whether this item is disabled. */
@@ -460,19 +527,28 @@ class RdxMenuCheckboxItem {
460
527
  this.checked = model(false, ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
461
528
  /** Emits when the checked state changes. */
462
529
  this.onCheckedChange = output();
463
- this.highlighted = computed(() => this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
530
+ this.highlighted = computed(() => this.rootContext?.activeIndex() === this.listItem.index() || this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
464
531
  this.effectiveDisabled = computed(() => this.disabled() || (this.rootContext?.disabled() ?? false), ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
465
532
  // Expose helpers for host bindings
466
533
  this.isIndeterminate = isIndeterminate;
467
534
  this.getCheckedState = getCheckedState;
535
+ effect(() => {
536
+ this.listItem.setMetadata({
537
+ type: 'checkbox-item',
538
+ disabled: this.effectiveDisabled(),
539
+ label: this.label()
540
+ });
541
+ });
468
542
  }
469
543
  onFocus() {
470
- if (!this.effectiveDisabled()) {
544
+ if (!this.rootContext?.disabled()) {
471
545
  this.isFocused.set(true);
472
546
  }
547
+ this.setActiveIndex();
473
548
  }
474
549
  onBlur() {
475
550
  this.isFocused.set(false);
551
+ this.clearActiveIndex();
476
552
  }
477
553
  onPointerMove(event) {
478
554
  if (event.defaultPrevented || event.pointerType !== 'mouse' || this.effectiveDisabled()) {
@@ -481,6 +557,7 @@ class RdxMenuCheckboxItem {
481
557
  if (this.rootContext && !this.rootContext.highlightItemOnHover()) {
482
558
  return;
483
559
  }
560
+ this.setActiveIndex();
484
561
  if (this.elementRef.nativeElement.ownerDocument.activeElement !== this.elementRef.nativeElement) {
485
562
  this.elementRef.nativeElement.focus({ preventScroll: true });
486
563
  }
@@ -490,6 +567,8 @@ class RdxMenuCheckboxItem {
490
567
  return;
491
568
  }
492
569
  if (this.elementRef.nativeElement.ownerDocument.activeElement === this.elementRef.nativeElement) {
570
+ this.isFocused.set(false);
571
+ this.clearActiveIndex();
493
572
  this.elementRef.nativeElement.closest('[rdxMenuPopup]')?.focus({ preventScroll: true });
494
573
  }
495
574
  }
@@ -520,8 +599,22 @@ class RdxMenuCheckboxItem {
520
599
  this.checked.set(next);
521
600
  this.onCheckedChange.emit(next);
522
601
  }
602
+ setActiveIndex() {
603
+ if (!this.rootContext || this.rootContext.disabled()) {
604
+ return;
605
+ }
606
+ const index = this.listItem.index();
607
+ if (index !== -1) {
608
+ this.rootContext.setActiveIndex(index);
609
+ }
610
+ }
611
+ clearActiveIndex() {
612
+ if (this.rootContext?.activeIndex() === this.listItem.index()) {
613
+ this.rootContext.setActiveIndex(null);
614
+ }
615
+ }
523
616
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuCheckboxItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
524
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuCheckboxItem, isStandalone: true, selector: "[rdxMenuCheckboxItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", onCheckedChange: "onCheckedChange" }, host: { attributes: { "role": "menuitemcheckbox", "tabindex": "-1" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick()", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.aria-checked": "isIndeterminate(checked()) ? \"mixed\" : checked()", "attr.data-state": "getCheckedState(checked())", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, providers: [provideRdxMenuCheckboxItemContext(checkboxItemContextFactory)], exportAs: ["rdxMenuCheckboxItem"], ngImport: i0 }); }
617
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuCheckboxItem, isStandalone: true, selector: "[rdxMenuCheckboxItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", onCheckedChange: "onCheckedChange" }, host: { attributes: { "role": "menuitemcheckbox" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick()", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.tabindex": "rootContext?.isOpen() && highlighted() ? 0 : -1", "attr.aria-checked": "isIndeterminate(checked()) ? \"mixed\" : checked()", "attr.data-state": "getCheckedState(checked())", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, providers: [provideRdxMenuCheckboxItemContext(checkboxItemContextFactory)], exportAs: ["rdxMenuCheckboxItem"], hostDirectives: [{ directive: i1$1.RdxCompositeListItem }], ngImport: i0 }); }
525
618
  }
526
619
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuCheckboxItem, decorators: [{
527
620
  type: Directive,
@@ -529,9 +622,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
529
622
  selector: '[rdxMenuCheckboxItem]',
530
623
  exportAs: 'rdxMenuCheckboxItem',
531
624
  providers: [provideRdxMenuCheckboxItemContext(checkboxItemContextFactory)],
625
+ hostDirectives: [RdxCompositeListItem],
532
626
  host: {
533
627
  role: 'menuitemcheckbox',
534
- tabindex: '-1',
628
+ '[attr.tabindex]': 'rootContext?.isOpen() && highlighted() ? 0 : -1',
535
629
  '[attr.aria-checked]': 'isIndeterminate(checked()) ? "mixed" : checked()',
536
630
  '[attr.data-state]': 'getCheckedState(checked())',
537
631
  '[attr.data-disabled]': 'effectiveDisabled() ? "" : undefined',
@@ -548,7 +642,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
548
642
  '(keydown.space)': 'onActivate($event)'
549
643
  }
550
644
  }]
551
- }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], onCheckedChange: [{ type: i0.Output, args: ["onCheckedChange"] }] } });
645
+ }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], checked: [{ type: i0.Input, args: [{ isSignal: true, alias: "checked", required: false }] }, { type: i0.Output, args: ["checkedChange"] }], onCheckedChange: [{ type: i0.Output, args: ["onCheckedChange"] }] } });
552
646
 
553
647
  /**
554
648
  * Renders when the parent checkbox item is checked or indeterminate.
@@ -642,6 +736,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
642
736
  class RdxMenuItem {
643
737
  constructor() {
644
738
  this.rootContext = injectRdxMenuRootContext(true);
739
+ this.listItem = inject(RdxCompositeListItem, { self: true });
645
740
  this.elementRef = inject(ElementRef);
646
741
  this.isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
647
742
  /** Whether this item is disabled. */
@@ -652,16 +747,25 @@ class RdxMenuItem {
652
747
  this.label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
653
748
  /** Emits when the item is selected. */
654
749
  this.onSelect = output();
655
- this.highlighted = computed(() => this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
750
+ this.highlighted = computed(() => this.rootContext?.activeIndex() === this.listItem.index() || this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
656
751
  this.effectiveDisabled = computed(() => this.disabled() || (this.rootContext?.disabled() ?? false), ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
752
+ effect(() => {
753
+ this.listItem.setMetadata({
754
+ type: 'regular-item',
755
+ disabled: this.effectiveDisabled(),
756
+ label: this.label()
757
+ });
758
+ });
657
759
  }
658
760
  onFocus() {
659
- if (!this.effectiveDisabled()) {
761
+ if (!this.rootContext?.disabled()) {
660
762
  this.isFocused.set(true);
661
763
  }
764
+ this.setActiveIndex();
662
765
  }
663
766
  onBlur() {
664
767
  this.isFocused.set(false);
768
+ this.clearActiveIndex();
665
769
  }
666
770
  onPointerMove(event) {
667
771
  if (event.defaultPrevented || event.pointerType !== 'mouse' || this.effectiveDisabled()) {
@@ -670,6 +774,7 @@ class RdxMenuItem {
670
774
  if (this.rootContext && !this.rootContext.highlightItemOnHover()) {
671
775
  return;
672
776
  }
777
+ this.setActiveIndex();
673
778
  if (this.elementRef.nativeElement.ownerDocument.activeElement !== this.elementRef.nativeElement) {
674
779
  this.elementRef.nativeElement.focus({ preventScroll: true });
675
780
  }
@@ -681,6 +786,8 @@ class RdxMenuItem {
681
786
  // Clear highlight when the pointer leaves: move focus back to the popup. A subsequent
682
787
  // pointermove on a sibling item re-focuses it, so moving between items still works.
683
788
  if (this.elementRef.nativeElement.ownerDocument.activeElement === this.elementRef.nativeElement) {
789
+ this.isFocused.set(false);
790
+ this.clearActiveIndex();
684
791
  this.elementRef.nativeElement.closest('[rdxMenuPopup]')?.focus({ preventScroll: true });
685
792
  }
686
793
  }
@@ -706,17 +813,32 @@ class RdxMenuItem {
706
813
  if (this.closeOnClick())
707
814
  this.rootContext?.closeEntireMenu();
708
815
  }
816
+ setActiveIndex() {
817
+ if (!this.rootContext || this.rootContext.disabled()) {
818
+ return;
819
+ }
820
+ const index = this.listItem.index();
821
+ if (index !== -1) {
822
+ this.rootContext.setActiveIndex(index);
823
+ }
824
+ }
825
+ clearActiveIndex() {
826
+ if (this.rootContext?.activeIndex() === this.listItem.index()) {
827
+ this.rootContext.setActiveIndex(null);
828
+ }
829
+ }
709
830
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
710
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuItem, isStandalone: true, selector: "[rdxMenuItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { attributes: { "role": "menuitem", "tabindex": "-1" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick()", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, exportAs: ["rdxMenuItem"], ngImport: i0 }); }
831
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuItem, isStandalone: true, selector: "[rdxMenuItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { attributes: { "role": "menuitem" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick()", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.tabindex": "rootContext?.isOpen() && highlighted() ? 0 : -1", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, exportAs: ["rdxMenuItem"], hostDirectives: [{ directive: i1$1.RdxCompositeListItem }], ngImport: i0 }); }
711
832
  }
712
833
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuItem, decorators: [{
713
834
  type: Directive,
714
835
  args: [{
715
836
  selector: '[rdxMenuItem]',
716
837
  exportAs: 'rdxMenuItem',
838
+ hostDirectives: [RdxCompositeListItem],
717
839
  host: {
718
840
  role: 'menuitem',
719
- tabindex: '-1',
841
+ '[attr.tabindex]': 'rootContext?.isOpen() && highlighted() ? 0 : -1',
720
842
  '[attr.data-disabled]': 'effectiveDisabled() ? "" : undefined',
721
843
  '[attr.aria-disabled]': 'effectiveDisabled() ? true : undefined',
722
844
  '[attr.data-highlighted]': 'highlighted() ? "" : undefined',
@@ -731,7 +853,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
731
853
  '(keydown.space)': 'onActivate($event)'
732
854
  }
733
855
  }]
734
- }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }] } });
856
+ }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }] } });
735
857
 
736
858
  /**
737
859
  * A menu item that renders as a link.
@@ -739,6 +861,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
739
861
  class RdxMenuLinkItem {
740
862
  constructor() {
741
863
  this.rootContext = injectRdxMenuRootContext(true);
864
+ this.listItem = inject(RdxCompositeListItem, { self: true });
742
865
  this.elementRef = inject(ElementRef);
743
866
  this.isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
744
867
  /** Whether this item is disabled. */
@@ -749,16 +872,25 @@ class RdxMenuLinkItem {
749
872
  this.label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
750
873
  /** Emits when the item is selected. */
751
874
  this.onSelect = output();
752
- this.highlighted = computed(() => this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
875
+ this.highlighted = computed(() => this.rootContext?.activeIndex() === this.listItem.index() || this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
753
876
  this.effectiveDisabled = computed(() => this.disabled() || (this.rootContext?.disabled() ?? false), ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
877
+ effect(() => {
878
+ this.listItem.setMetadata({
879
+ type: 'link-item',
880
+ disabled: this.effectiveDisabled(),
881
+ label: this.label()
882
+ });
883
+ });
754
884
  }
755
885
  onFocus() {
756
- if (!this.effectiveDisabled()) {
886
+ if (!this.rootContext?.disabled()) {
757
887
  this.isFocused.set(true);
758
888
  }
889
+ this.setActiveIndex();
759
890
  }
760
891
  onBlur() {
761
892
  this.isFocused.set(false);
893
+ this.clearActiveIndex();
762
894
  }
763
895
  onPointerMove(event) {
764
896
  if (event.defaultPrevented || event.pointerType !== 'mouse' || this.effectiveDisabled()) {
@@ -767,6 +899,7 @@ class RdxMenuLinkItem {
767
899
  if (this.rootContext && !this.rootContext.highlightItemOnHover()) {
768
900
  return;
769
901
  }
902
+ this.setActiveIndex();
770
903
  if (this.elementRef.nativeElement.ownerDocument.activeElement !== this.elementRef.nativeElement) {
771
904
  this.elementRef.nativeElement.focus({ preventScroll: true });
772
905
  }
@@ -776,6 +909,8 @@ class RdxMenuLinkItem {
776
909
  return;
777
910
  }
778
911
  if (this.elementRef.nativeElement.ownerDocument.activeElement === this.elementRef.nativeElement) {
912
+ this.isFocused.set(false);
913
+ this.clearActiveIndex();
779
914
  this.elementRef.nativeElement.closest('[rdxMenuPopup]')?.focus({ preventScroll: true });
780
915
  }
781
916
  }
@@ -796,25 +931,38 @@ class RdxMenuLinkItem {
796
931
  this.elementRef.nativeElement.click();
797
932
  }
798
933
  onActivate(event) {
934
+ event.preventDefault();
799
935
  if (this.effectiveDisabled()) {
800
- event.preventDefault();
801
936
  return;
802
937
  }
803
- this.onSelect.emit();
804
- if (this.closeOnClick())
805
- this.rootContext?.closeEntireMenu();
938
+ this.elementRef.nativeElement.click();
939
+ }
940
+ setActiveIndex() {
941
+ if (!this.rootContext || this.rootContext.disabled()) {
942
+ return;
943
+ }
944
+ const index = this.listItem.index();
945
+ if (index !== -1) {
946
+ this.rootContext.setActiveIndex(index);
947
+ }
948
+ }
949
+ clearActiveIndex() {
950
+ if (this.rootContext?.activeIndex() === this.listItem.index()) {
951
+ this.rootContext.setActiveIndex(null);
952
+ }
806
953
  }
807
954
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuLinkItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
808
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuLinkItem, isStandalone: true, selector: "a[rdxMenuLinkItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { attributes: { "role": "menuitem", "tabindex": "-1" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick($event)", "keydown.enter": "onActivate($event)" }, properties: { "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, exportAs: ["rdxMenuLinkItem"], ngImport: i0 }); }
955
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuLinkItem, isStandalone: true, selector: "a[rdxMenuLinkItem]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { attributes: { "role": "menuitem" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick($event)", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.tabindex": "rootContext?.isOpen() && highlighted() ? 0 : -1", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, exportAs: ["rdxMenuLinkItem"], hostDirectives: [{ directive: i1$1.RdxCompositeListItem }], ngImport: i0 }); }
809
956
  }
810
957
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuLinkItem, decorators: [{
811
958
  type: Directive,
812
959
  args: [{
813
960
  selector: 'a[rdxMenuLinkItem]',
814
961
  exportAs: 'rdxMenuLinkItem',
962
+ hostDirectives: [RdxCompositeListItem],
815
963
  host: {
816
964
  role: 'menuitem',
817
- tabindex: '-1',
965
+ '[attr.tabindex]': 'rootContext?.isOpen() && highlighted() ? 0 : -1',
818
966
  '[attr.data-disabled]': 'effectiveDisabled() ? "" : undefined',
819
967
  '[attr.aria-disabled]': 'effectiveDisabled() ? true : undefined',
820
968
  '[attr.data-highlighted]': 'highlighted() ? "" : undefined',
@@ -825,10 +973,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
825
973
  '(pointerleave)': 'onPointerLeave($event)',
826
974
  '(mouseup)': 'onMouseUp($event)',
827
975
  '(click)': 'onItemClick($event)',
828
- '(keydown.enter)': 'onActivate($event)'
976
+ '(keydown.enter)': 'onActivate($event)',
977
+ '(keydown.space)': 'onActivate($event)'
829
978
  }
830
979
  }]
831
- }], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }] } });
980
+ }], ctorParameters: () => [], propDecorators: { disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }] } });
832
981
 
833
982
  /**
834
983
  * A container for the menu contents.
@@ -840,6 +989,7 @@ class RdxMenuPopup {
840
989
  this.registration = inject(RDX_FLOATING_REGISTRATION, { optional: true });
841
990
  this.focusManager = inject(RdxFloatingFocusManager);
842
991
  this.focusScope = inject(RdxFocusScope);
992
+ this.compositeList = inject(RdxCompositeList, { self: true });
843
993
  this.wrapper = inject(RdxPopperContentWrapper, { optional: true });
844
994
  this.elementRef = inject(ElementRef);
845
995
  this.search = '';
@@ -954,10 +1104,11 @@ class RdxMenuPopup {
954
1104
  }
955
1105
  }
956
1106
  handleKeydown(event) {
957
- const el = this.elementRef.nativeElement;
958
- const items = getFocusableMenuItems(el);
959
- const current = el.ownerDocument.activeElement;
960
- const currentIndex = items.indexOf(current);
1107
+ if (this.rootContext.disabled()) {
1108
+ return;
1109
+ }
1110
+ const items = this.menuItems();
1111
+ const currentIndex = this.currentItemIndex(items);
961
1112
  switch (event.key) {
962
1113
  case 'ArrowDown': {
963
1114
  event.preventDefault();
@@ -968,7 +1119,7 @@ class RdxMenuPopup {
968
1119
  ? items[0]
969
1120
  : items[items.length - 1]
970
1121
  : items[currentIndex + 1];
971
- next?.focus({ preventScroll: true });
1122
+ this.focusMenuItem(next);
972
1123
  break;
973
1124
  }
974
1125
  case 'ArrowUp': {
@@ -980,19 +1131,19 @@ class RdxMenuPopup {
980
1131
  ? items[items.length - 1]
981
1132
  : items[0]
982
1133
  : items[currentIndex - 1];
983
- prev?.focus({ preventScroll: true });
1134
+ this.focusMenuItem(prev);
984
1135
  break;
985
1136
  }
986
1137
  case 'Home': {
987
1138
  event.preventDefault();
988
1139
  event.stopPropagation();
989
- items[0]?.focus({ preventScroll: true });
1140
+ this.focusMenuItem(items[0]);
990
1141
  break;
991
1142
  }
992
1143
  case 'End': {
993
1144
  event.preventDefault();
994
1145
  event.stopPropagation();
995
- items[items.length - 1]?.focus({ preventScroll: true });
1146
+ this.focusMenuItem(items[items.length - 1]);
996
1147
  break;
997
1148
  }
998
1149
  case 'ArrowLeft': {
@@ -1055,11 +1206,8 @@ class RdxMenuPopup {
1055
1206
  const query = this.search.length > 1 && [...this.search].every((c) => c === char) ? char : this.search;
1056
1207
  const startIndex = currentIndex >= 0 ? currentIndex + 1 : 0;
1057
1208
  const rotated = [...items.slice(startIndex), ...items.slice(0, startIndex)];
1058
- const match = rotated.find((item) => {
1059
- const text = (item.dataset['label'] ?? item.textContent?.trim() ?? '').toLowerCase();
1060
- return text.startsWith(query);
1061
- });
1062
- match?.focus({ preventScroll: true });
1209
+ const match = rotated.find((item) => item.label.startsWith(query));
1210
+ this.focusMenuItem(match);
1063
1211
  }
1064
1212
  break;
1065
1213
  }
@@ -1079,14 +1227,34 @@ class RdxMenuPopup {
1079
1227
  if (activeElement && popup.contains(activeElement)) {
1080
1228
  return;
1081
1229
  }
1082
- const items = getFocusableMenuItems(popup);
1230
+ const items = this.menuItems();
1083
1231
  if (items.length === 0) {
1084
1232
  if (attempt < maxAttempts) {
1085
1233
  this.scheduleSubmenuKeyboardFocus(attempt + 1);
1086
1234
  }
1087
1235
  return;
1088
1236
  }
1089
- items[0]?.focus({ preventScroll: true });
1237
+ this.focusMenuItem(items[0]);
1238
+ }
1239
+ menuItems() {
1240
+ const compositeItems = getCompositeMenuItems(this.compositeList);
1241
+ return compositeItems.length > 0 ? compositeItems : getDomMenuItems(this.elementRef.nativeElement);
1242
+ }
1243
+ currentItemIndex(items) {
1244
+ const current = this.elementRef.nativeElement.ownerDocument.activeElement;
1245
+ const focusedIndex = items.findIndex((item) => item.element === current);
1246
+ if (focusedIndex !== -1) {
1247
+ return focusedIndex;
1248
+ }
1249
+ const activeIndex = this.rootContext.activeIndex();
1250
+ return items.findIndex((item) => item.index === activeIndex);
1251
+ }
1252
+ focusMenuItem(item) {
1253
+ if (!item) {
1254
+ return;
1255
+ }
1256
+ this.rootContext.setActiveIndex(item.index);
1257
+ item.element.focus({ preventScroll: true });
1090
1258
  }
1091
1259
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuPopup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1092
1260
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxMenuPopup, isStandalone: true, selector: "[rdxMenuPopup]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside", focusOutside: "focusOutside", interactOutside: "interactOutside", openAutoFocus: "openAutoFocus", closeAutoFocus: "closeAutoFocus" }, host: { attributes: { "role": "menu", "tabindex": "-1" }, listeners: { "keydown": "handleKeydown($event)", "rdx-menu-close-parent": "handleCloseParent($event)" }, properties: { "attr.aria-orientation": "rootContext.orientation()", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-state": "rootContext.isOpen() ? \"open\" : \"closed\"", "attr.data-starting-style": "rootContext.transitionStatus() === \"starting\" ? \"\" : undefined", "attr.data-ending-style": "rootContext.transitionStatus() === \"ending\" ? \"\" : undefined", "attr.data-align": "align()", "attr.data-side": "side()" } }, providers: [
@@ -1138,14 +1306,14 @@ class RdxMenuPopup {
1138
1306
  closeInteractionType: () => rootContext.closeInteractionType()
1139
1307
  };
1140
1308
  })
1141
- ], exportAs: ["rdxMenuPopup"], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxFloatingNodeRegistration }, { directive: i3.RdxFloatingFocusManager }], ngImport: i0 }); }
1309
+ ], exportAs: ["rdxMenuPopup"], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxFloatingNodeRegistration }, { directive: i3.RdxFloatingFocusManager }, { directive: i1$1.RdxCompositeList }], ngImport: i0 }); }
1142
1310
  }
1143
1311
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuPopup, decorators: [{
1144
1312
  type: Directive,
1145
1313
  args: [{
1146
1314
  selector: '[rdxMenuPopup]',
1147
1315
  exportAs: 'rdxMenuPopup',
1148
- hostDirectives: [RdxPopperContent, RdxFloatingNodeRegistration, RdxFloatingFocusManager],
1316
+ hostDirectives: [RdxPopperContent, RdxFloatingNodeRegistration, RdxFloatingFocusManager, RdxCompositeList],
1149
1317
  providers: [
1150
1318
  provideFloatingFocusManagerConfig(() => {
1151
1319
  const rootContext = injectRdxMenuRootContext();
@@ -1224,7 +1392,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1224
1392
  */
1225
1393
  class RdxMenuPortal {
1226
1394
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1227
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxMenuPortal, isStandalone: true, selector: "ng-template[rdxMenuPortal]", providers: [provideRdxPresenceContext(() => ({ present: injectRdxMenuRootContext().present }))], exportAs: ["rdxMenuPortal"], hostDirectives: [{ directive: i1$1.RdxPortalPresence, inputs: ["container", "container"] }], ngImport: i0 }); }
1395
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxMenuPortal, isStandalone: true, selector: "ng-template[rdxMenuPortal]", providers: [provideRdxPresenceContext(() => ({ present: injectRdxMenuRootContext().present }))], exportAs: ["rdxMenuPortal"], hostDirectives: [{ directive: i1$2.RdxPortalPresence, inputs: ["container", "container"] }], ngImport: i0 }); }
1228
1396
  }
1229
1397
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuPortal, decorators: [{
1230
1398
  type: Directive,
@@ -1422,6 +1590,7 @@ class RdxMenuRadioItem {
1422
1590
  constructor() {
1423
1591
  this.rootContext = injectRdxMenuRootContext(true);
1424
1592
  this.radioGroupContext = injectRdxMenuRadioGroupContext();
1593
+ this.listItem = inject(RdxCompositeListItem, { self: true });
1425
1594
  this.elementRef = inject(ElementRef);
1426
1595
  this.isFocused = signal(false, ...(ngDevMode ? [{ debugName: "isFocused" }] : /* istanbul ignore next */ []));
1427
1596
  /** The value of this radio item. */
@@ -1435,17 +1604,26 @@ class RdxMenuRadioItem {
1435
1604
  /** Emits when this item is selected. */
1436
1605
  this.onSelect = output();
1437
1606
  this.checked = computed(() => this.radioGroupContext.value() === this.value(), ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
1438
- this.highlighted = computed(() => this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
1607
+ this.highlighted = computed(() => this.rootContext?.activeIndex() === this.listItem.index() || this.isFocused(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
1439
1608
  this.effectiveDisabled = computed(() => this.disabled() || this.radioGroupContext.disabled() || (this.rootContext?.disabled() ?? false), ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
1440
1609
  this.getCheckedState = getCheckedState;
1610
+ effect(() => {
1611
+ this.listItem.setMetadata({
1612
+ type: 'radio-item',
1613
+ disabled: this.effectiveDisabled(),
1614
+ label: this.label()
1615
+ });
1616
+ });
1441
1617
  }
1442
1618
  onFocus() {
1443
- if (!this.effectiveDisabled()) {
1619
+ if (!this.rootContext?.disabled()) {
1444
1620
  this.isFocused.set(true);
1445
1621
  }
1622
+ this.setActiveIndex();
1446
1623
  }
1447
1624
  onBlur() {
1448
1625
  this.isFocused.set(false);
1626
+ this.clearActiveIndex();
1449
1627
  }
1450
1628
  onPointerMove(event) {
1451
1629
  if (event.defaultPrevented || event.pointerType !== 'mouse' || this.effectiveDisabled()) {
@@ -1454,6 +1632,7 @@ class RdxMenuRadioItem {
1454
1632
  if (this.rootContext && !this.rootContext.highlightItemOnHover()) {
1455
1633
  return;
1456
1634
  }
1635
+ this.setActiveIndex();
1457
1636
  if (this.elementRef.nativeElement.ownerDocument.activeElement !== this.elementRef.nativeElement) {
1458
1637
  this.elementRef.nativeElement.focus({ preventScroll: true });
1459
1638
  }
@@ -1463,6 +1642,8 @@ class RdxMenuRadioItem {
1463
1642
  return;
1464
1643
  }
1465
1644
  if (this.elementRef.nativeElement.ownerDocument.activeElement === this.elementRef.nativeElement) {
1645
+ this.isFocused.set(false);
1646
+ this.clearActiveIndex();
1466
1647
  this.elementRef.nativeElement.closest('[rdxMenuPopup]')?.focus({ preventScroll: true });
1467
1648
  }
1468
1649
  }
@@ -1493,8 +1674,22 @@ class RdxMenuRadioItem {
1493
1674
  if (this.closeOnClick())
1494
1675
  this.rootContext?.closeEntireMenu();
1495
1676
  }
1677
+ setActiveIndex() {
1678
+ if (!this.rootContext || this.rootContext.disabled()) {
1679
+ return;
1680
+ }
1681
+ const index = this.listItem.index();
1682
+ if (index !== -1) {
1683
+ this.rootContext.setActiveIndex(index);
1684
+ }
1685
+ }
1686
+ clearActiveIndex() {
1687
+ if (this.rootContext?.activeIndex() === this.listItem.index()) {
1688
+ this.rootContext.setActiveIndex(null);
1689
+ }
1690
+ }
1496
1691
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuRadioItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
1497
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuRadioItem, isStandalone: true, selector: "[rdxMenuRadioItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { attributes: { "role": "menuitemradio", "tabindex": "-1" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick()", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.aria-checked": "checked()", "attr.data-state": "getCheckedState(checked())", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, providers: [provideRdxMenuRadioItemContext(radioItemContextFactory)], exportAs: ["rdxMenuRadioItem"], ngImport: i0 }); }
1692
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuRadioItem, isStandalone: true, selector: "[rdxMenuRadioItem]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { onSelect: "onSelect" }, host: { attributes: { "role": "menuitemradio" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave($event)", "mouseup": "onMouseUp($event)", "click": "onItemClick()", "keydown.enter": "onActivate($event)", "keydown.space": "onActivate($event)" }, properties: { "attr.tabindex": "rootContext?.isOpen() && highlighted() ? 0 : -1", "attr.aria-checked": "checked()", "attr.data-state": "getCheckedState(checked())", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, providers: [provideRdxMenuRadioItemContext(radioItemContextFactory)], exportAs: ["rdxMenuRadioItem"], hostDirectives: [{ directive: i1$1.RdxCompositeListItem }], ngImport: i0 }); }
1498
1693
  }
1499
1694
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuRadioItem, decorators: [{
1500
1695
  type: Directive,
@@ -1502,9 +1697,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1502
1697
  selector: '[rdxMenuRadioItem]',
1503
1698
  exportAs: 'rdxMenuRadioItem',
1504
1699
  providers: [provideRdxMenuRadioItemContext(radioItemContextFactory)],
1700
+ hostDirectives: [RdxCompositeListItem],
1505
1701
  host: {
1506
1702
  role: 'menuitemradio',
1507
- tabindex: '-1',
1703
+ '[attr.tabindex]': 'rootContext?.isOpen() && highlighted() ? 0 : -1',
1508
1704
  '[attr.aria-checked]': 'checked()',
1509
1705
  '[attr.data-state]': 'getCheckedState(checked())',
1510
1706
  '[attr.data-disabled]': 'effectiveDisabled() ? "" : undefined',
@@ -1521,7 +1717,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1521
1717
  '(keydown.space)': 'onActivate($event)'
1522
1718
  }
1523
1719
  }]
1524
- }], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }] } });
1720
+ }], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], onSelect: [{ type: i0.Output, args: ["onSelect"] }] } });
1525
1721
 
1526
1722
  /**
1527
1723
  * Renders when the parent radio item is selected.
@@ -1915,6 +2111,8 @@ class RdxMenuSubTrigger {
1915
2111
  constructor() {
1916
2112
  this.submenuContext = injectRdxMenuRootContext();
1917
2113
  this.submenuRoot = inject(RdxMenuRoot);
2114
+ this.parentMenuRoot = this.submenuRoot.parentRoot;
2115
+ this.listItem = inject(RdxCompositeListItem, { self: true });
1918
2116
  this.elementRef = inject(ElementRef);
1919
2117
  this.destroyRef = inject(DestroyRef);
1920
2118
  this.isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
@@ -1936,8 +2134,10 @@ class RdxMenuSubTrigger {
1936
2134
  this.closeDelay = input(0, { ...(ngDevMode ? { debugName: "closeDelay" } : /* istanbul ignore next */ {}), transform: numberOrUndefined$1 });
1937
2135
  /** Explicit typeahead label. When set, overrides textContent for character search. */
1938
2136
  this.label = input(undefined, ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
1939
- /** Highlighted when focused OR while the submenu is open. */
1940
- this.highlighted = computed(() => this.isFocused() || this.submenuContext.isOpen(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
2137
+ /** Highlighted when active in the parent menu or while the submenu is open. */
2138
+ this.highlighted = computed(() => this.parentMenuRoot?.activeIndex() === this.listItem.index() ||
2139
+ this.isFocused() ||
2140
+ this.submenuContext.isOpen(), ...(ngDevMode ? [{ debugName: "highlighted" }] : /* istanbul ignore next */ []));
1941
2141
  this.effectiveDisabled = computed(() => this.disabled() || this.submenuContext.disabled(), ...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
1942
2142
  this.nativeButtonState = computed(() => this.nativeButton() || this.elementRef.nativeElement.tagName === 'BUTTON', ...(ngDevMode ? [{ debugName: "nativeButtonState" }] : /* istanbul ignore next */ []));
1943
2143
  this.submenuContext.markAsSubmenu();
@@ -1950,6 +2150,13 @@ class RdxMenuSubTrigger {
1950
2150
  submenuRootsByTrigger.delete(el);
1951
2151
  });
1952
2152
  });
2153
+ effect(() => {
2154
+ this.listItem.setMetadata({
2155
+ type: 'submenu-trigger',
2156
+ disabled: this.effectiveDisabled(),
2157
+ label: this.label()
2158
+ });
2159
+ });
1953
2160
  // While this submenu is open by hover, it owns the decision to close itself: a document
1954
2161
  // `mousemove` handler keeps it open while the cursor traverses the safe polygon toward the
1955
2162
  // popup, and a pointer-events tunnel stops siblings from stealing it mid-traversal.
@@ -2011,13 +2218,16 @@ class RdxMenuSubTrigger {
2011
2218
  }
2012
2219
  }
2013
2220
  onFocus() {
2014
- if (!this.effectiveDisabled()) {
2015
- this.clearSiblingHighlights();
2016
- this.isFocused.set(true);
2221
+ if (this.submenuContext.disabled()) {
2222
+ return;
2017
2223
  }
2224
+ this.clearSiblingHighlights();
2225
+ this.isFocused.set(true);
2226
+ this.setParentActiveIndex();
2018
2227
  }
2019
2228
  onBlur() {
2020
2229
  this.isFocused.set(false);
2230
+ this.clearParentActiveIndex();
2021
2231
  }
2022
2232
  onClick(event) {
2023
2233
  if (this.effectiveDisabled())
@@ -2100,6 +2310,7 @@ class RdxMenuSubTrigger {
2100
2310
  return;
2101
2311
  this.lastPointer = { x: event.clientX, y: event.clientY };
2102
2312
  this.clearSiblingHighlights();
2313
+ this.setParentActiveIndex();
2103
2314
  const el = this.elementRef.nativeElement;
2104
2315
  if (this.submenuContext.highlightItemOnHover() && el.ownerDocument.activeElement !== el) {
2105
2316
  el.focus({ preventScroll: true });
@@ -2118,6 +2329,7 @@ class RdxMenuSubTrigger {
2118
2329
  }
2119
2330
  clearHighlight() {
2120
2331
  this.isFocused.set(false);
2332
+ this.clearParentActiveIndex();
2121
2333
  }
2122
2334
  closeSiblingSubmenus() {
2123
2335
  const currentTrigger = this.elementRef.nativeElement;
@@ -2177,23 +2389,34 @@ class RdxMenuSubTrigger {
2177
2389
  setTimeout(run);
2178
2390
  }
2179
2391
  }
2392
+ setParentActiveIndex() {
2393
+ const index = this.listItem.index();
2394
+ if (index === -1 || !this.parentMenuRoot || this.parentMenuRoot.effectiveDisabled()) {
2395
+ return;
2396
+ }
2397
+ this.parentMenuRoot.setActiveIndex(index);
2398
+ }
2399
+ clearParentActiveIndex() {
2400
+ if (this.parentMenuRoot?.activeIndex() === this.listItem.index()) {
2401
+ this.parentMenuRoot.setActiveIndex(null);
2402
+ }
2403
+ }
2180
2404
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuSubTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2181
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuSubTrigger, isStandalone: true, selector: "[rdxMenuSubTrigger]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, nativeButton: { classPropertyName: "nativeButton", publicName: "nativeButton", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem", "tabindex": "-1" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "click": "onClick($event)", "keydown.enter": "onEnter($event)", "keydown.arrowleft": "onArrowLeft($event)", "keydown.arrowright": "onArrowRight($event)", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave()", "rdx-menu-subtrigger-clear-highlight": "clearHighlight()" }, properties: { "attr.type": "nativeButtonState() ? \"button\" : undefined", "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "submenuContext.isOpen()", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.disabled": "nativeButtonState() && effectiveDisabled() ? \"\" : undefined", "attr.data-state": "submenuContext.isOpen() ? \"open\" : \"closed\"", "attr.data-popup-open": "submenuContext.isOpen() ? \"\" : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, exportAs: ["rdxMenuSubTrigger"], hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
2405
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuSubTrigger, isStandalone: true, selector: "[rdxMenuSubTrigger]", inputs: { disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, nativeButton: { classPropertyName: "nativeButton", publicName: "nativeButton", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem" }, listeners: { "focus": "onFocus()", "blur": "onBlur()", "click": "onClick($event)", "keydown.enter": "onEnter($event)", "keydown.space": "onEnter($event)", "keydown.arrowleft": "onArrowLeft($event)", "keydown.arrowright": "onArrowRight($event)", "pointermove": "onPointerMove($event)", "pointerleave": "onPointerLeave()", "rdx-menu-subtrigger-clear-highlight": "clearHighlight()" }, properties: { "attr.type": "nativeButtonState() ? \"button\" : undefined", "attr.tabindex": "parentMenuRoot?.open() && highlighted() ? 0 : -1", "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "submenuContext.isOpen()", "attr.aria-disabled": "effectiveDisabled() ? true : undefined", "attr.data-state": "submenuContext.isOpen() ? \"open\" : \"closed\"", "attr.data-popup-open": "submenuContext.isOpen() ? \"\" : undefined", "attr.data-highlighted": "highlighted() ? \"\" : undefined", "attr.data-disabled": "effectiveDisabled() ? \"\" : undefined", "attr.data-label": "label() ?? undefined" } }, exportAs: ["rdxMenuSubTrigger"], hostDirectives: [{ directive: i1.RdxPopperAnchor }, { directive: i1$1.RdxCompositeListItem }], ngImport: i0 }); }
2182
2406
  }
2183
2407
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuSubTrigger, decorators: [{
2184
2408
  type: Directive,
2185
2409
  args: [{
2186
2410
  selector: '[rdxMenuSubTrigger]',
2187
2411
  exportAs: 'rdxMenuSubTrigger',
2188
- hostDirectives: [RdxPopperAnchor],
2412
+ hostDirectives: [RdxPopperAnchor, RdxCompositeListItem],
2189
2413
  host: {
2190
2414
  '[attr.type]': 'nativeButtonState() ? "button" : undefined',
2191
2415
  role: 'menuitem',
2192
- tabindex: '-1',
2416
+ '[attr.tabindex]': 'parentMenuRoot?.open() && highlighted() ? 0 : -1',
2193
2417
  '[attr.aria-haspopup]': '"menu"',
2194
2418
  '[attr.aria-expanded]': 'submenuContext.isOpen()',
2195
2419
  '[attr.aria-disabled]': 'effectiveDisabled() ? true : undefined',
2196
- '[attr.disabled]': 'nativeButtonState() && effectiveDisabled() ? "" : undefined',
2197
2420
  '[attr.data-state]': 'submenuContext.isOpen() ? "open" : "closed"',
2198
2421
  '[attr.data-popup-open]': 'submenuContext.isOpen() ? "" : undefined',
2199
2422
  '[attr.data-highlighted]': 'highlighted() ? "" : undefined',
@@ -2203,6 +2426,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
2203
2426
  '(blur)': 'onBlur()',
2204
2427
  '(click)': 'onClick($event)',
2205
2428
  '(keydown.enter)': 'onEnter($event)',
2429
+ '(keydown.space)': 'onEnter($event)',
2206
2430
  '(keydown.arrowleft)': 'onArrowLeft($event)',
2207
2431
  '(keydown.arrowright)': 'onArrowRight($event)',
2208
2432
  '(pointermove)': 'onPointerMove($event)',
@@ -2226,6 +2450,7 @@ class RdxMenuTrigger {
2226
2450
  this.openedByHover = false;
2227
2451
  this.ignoreNextClick = null;
2228
2452
  this.handleDocumentMouseUp = (event) => {
2453
+ clearTimeout(this.allowMouseUpTriggerTimer);
2229
2454
  this.allowMouseUpTriggerTimer = undefined;
2230
2455
  this.rootContext.setAllowMouseUpTrigger(false);
2231
2456
  const trigger = this.elementRef.nativeElement;
@@ -2515,14 +2740,14 @@ class RdxMenuTrigger {
2515
2740
  }
2516
2741
  }
2517
2742
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
2518
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuTrigger, isStandalone: true, selector: "[rdxMenuTrigger]", inputs: { nativeButton: { classPropertyName: "nativeButton", publicName: "nativeButton", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointerdown": "handlePointerDown($event)", "mousedown": "handleMouseDown($event)", "click": "handleClick($event)", "pointerenter": "handlePointerEnter($event)", "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave($event)", "keydown.arrowdown": "handleArrowDown($event)", "keydown.arrowup": "handleArrowUp($event)", "keydown.arrowleft": "handleArrowLeft($event)", "keydown.arrowright": "handleArrowRight($event)", "keydown.home": "handleHome($event)", "keydown.end": "handleEnd($event)", "keydown.escape": "handleEscape($event)", "keydown.enter": "handleKeyboardToggle($event)", "keydown.space": "handleKeyboardToggle($event)" }, properties: { "attr.type": "nativeButtonState() ? \"button\" : undefined", "attr.role": "rootContext.hasTriggerInteractionHandler() ? \"menuitem\" : nativeButtonState() ? undefined : \"button\"", "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "triggerInteraction.ariaExpanded()", "attr.aria-disabled": "isDisabled() ? true : undefined", "attr.disabled": "nativeButtonState() && isDisabled() ? \"\" : undefined", "attr.data-state": "triggerInteraction.dataState()", "attr.data-disabled": "isDisabled() ? \"\" : undefined", "attr.data-popup-open": "triggerInteraction.dataPopupOpen()", "style.pointer-events": "rootContext.isOpen() && rootContext.modal() ? \"auto\" : undefined" } }, exportAs: ["rdxMenuTrigger"], hostDirectives: [{ directive: i1.RdxPopperAnchor }, { directive: i2$1.RdxCompositeItem }], ngImport: i0 }); }
2743
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxMenuTrigger, isStandalone: true, selector: "[rdxMenuTrigger]", inputs: { nativeButton: { classPropertyName: "nativeButton", publicName: "nativeButton", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, openOnHover: { classPropertyName: "openOnHover", publicName: "openOnHover", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointerdown": "handlePointerDown($event)", "mousedown": "handleMouseDown($event)", "click": "handleClick($event)", "pointerenter": "handlePointerEnter($event)", "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave($event)", "keydown.arrowdown": "handleArrowDown($event)", "keydown.arrowup": "handleArrowUp($event)", "keydown.arrowleft": "handleArrowLeft($event)", "keydown.arrowright": "handleArrowRight($event)", "keydown.home": "handleHome($event)", "keydown.end": "handleEnd($event)", "keydown.escape": "handleEscape($event)", "keydown.enter": "handleKeyboardToggle($event)", "keydown.space": "handleKeyboardToggle($event)" }, properties: { "attr.type": "nativeButtonState() ? \"button\" : undefined", "attr.role": "rootContext.hasTriggerInteractionHandler() ? \"menuitem\" : nativeButtonState() ? undefined : \"button\"", "attr.aria-haspopup": "\"menu\"", "attr.aria-expanded": "triggerInteraction.ariaExpanded()", "attr.aria-disabled": "isDisabled() ? true : undefined", "attr.disabled": "nativeButtonState() && isDisabled() ? \"\" : undefined", "attr.data-state": "triggerInteraction.dataState()", "attr.data-disabled": "isDisabled() ? \"\" : undefined", "attr.data-popup-open": "triggerInteraction.dataPopupOpen()", "style.pointer-events": "rootContext.isOpen() && rootContext.modal() ? \"auto\" : undefined" } }, exportAs: ["rdxMenuTrigger"], hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
2519
2744
  }
2520
2745
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxMenuTrigger, decorators: [{
2521
2746
  type: Directive,
2522
2747
  args: [{
2523
2748
  selector: '[rdxMenuTrigger]',
2524
2749
  exportAs: 'rdxMenuTrigger',
2525
- hostDirectives: [RdxPopperAnchor, RdxCompositeItem],
2750
+ hostDirectives: [RdxPopperAnchor],
2526
2751
  host: {
2527
2752
  '[attr.type]': 'nativeButtonState() ? "button" : undefined',
2528
2753
  '[attr.role]': 'rootContext.hasTriggerInteractionHandler() ? "menuitem" : nativeButtonState() ? undefined : "button"',