@radix-ng/primitives 1.0.0-beta.4 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/composite/README.md +3 -0
  2. package/fesm2022/radix-ng-primitives-accordion.mjs +12 -36
  3. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  4. package/fesm2022/radix-ng-primitives-checkbox.mjs +33 -18
  5. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  6. package/fesm2022/radix-ng-primitives-composite.mjs +515 -0
  7. package/fesm2022/radix-ng-primitives-composite.mjs.map +1 -0
  8. package/fesm2022/radix-ng-primitives-core.mjs +7 -0
  9. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-dialog.mjs +54 -12
  11. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  12. package/fesm2022/radix-ng-primitives-drawer.mjs +442 -2
  13. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
  14. package/fesm2022/radix-ng-primitives-editable.mjs +12 -7
  15. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  16. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +294 -8
  17. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-focus-scope.mjs +9 -0
  19. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-menu.mjs +71 -20
  21. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-menubar.mjs +68 -36
  23. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +281 -88
  25. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  26. package/fesm2022/radix-ng-primitives-number-field.mjs +7 -2
  27. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-popover.mjs +117 -35
  29. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-popper.mjs +73 -65
  31. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-radio.mjs +77 -36
  33. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  34. package/fesm2022/radix-ng-primitives-roving-focus.mjs +40 -8
  35. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  36. package/fesm2022/radix-ng-primitives-scroll-area.mjs +56 -25
  37. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  38. package/fesm2022/radix-ng-primitives-select.mjs +62 -37
  39. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  40. package/fesm2022/radix-ng-primitives-slider.mjs +259 -28
  41. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  42. package/fesm2022/radix-ng-primitives-stepper.mjs +11 -7
  43. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  44. package/fesm2022/radix-ng-primitives-switch.mjs +10 -5
  45. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  46. package/fesm2022/radix-ng-primitives-tabs.mjs +64 -30
  47. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  48. package/fesm2022/radix-ng-primitives-toggle-group.mjs +69 -19
  49. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  50. package/fesm2022/radix-ng-primitives-toggle.mjs +37 -13
  51. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  52. package/fesm2022/radix-ng-primitives-toolbar.mjs +50 -24
  53. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  54. package/fesm2022/radix-ng-primitives-tooltip.mjs +180 -35
  55. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  56. package/navigation-menu/README.md +5 -2
  57. package/package.json +5 -1
  58. package/types/radix-ng-primitives-accordion.d.ts +9 -13
  59. package/types/radix-ng-primitives-checkbox.d.ts +27 -15
  60. package/types/radix-ng-primitives-composite.d.ts +152 -0
  61. package/types/radix-ng-primitives-core.d.ts +2 -0
  62. package/types/radix-ng-primitives-dialog.d.ts +13 -2
  63. package/types/radix-ng-primitives-drawer.d.ts +40 -2
  64. package/types/radix-ng-primitives-editable.d.ts +11 -5
  65. package/types/radix-ng-primitives-floating-focus-manager.d.ts +113 -16
  66. package/types/radix-ng-primitives-menu.d.ts +13 -5
  67. package/types/radix-ng-primitives-menubar.d.ts +10 -5
  68. package/types/radix-ng-primitives-navigation-menu.d.ts +65 -33
  69. package/types/radix-ng-primitives-number-field.d.ts +8 -3
  70. package/types/radix-ng-primitives-popover.d.ts +26 -10
  71. package/types/radix-ng-primitives-popper.d.ts +1 -0
  72. package/types/radix-ng-primitives-radio.d.ts +22 -13
  73. package/types/radix-ng-primitives-roving-focus.d.ts +15 -1
  74. package/types/radix-ng-primitives-scroll-area.d.ts +4 -1
  75. package/types/radix-ng-primitives-select.d.ts +16 -20
  76. package/types/radix-ng-primitives-slider.d.ts +60 -9
  77. package/types/radix-ng-primitives-stepper.d.ts +11 -4
  78. package/types/radix-ng-primitives-switch.d.ts +10 -4
  79. package/types/radix-ng-primitives-tabs.d.ts +20 -11
  80. package/types/radix-ng-primitives-toggle-group.d.ts +34 -17
  81. package/types/radix-ng-primitives-toggle.d.ts +14 -7
  82. package/types/radix-ng-primitives-toolbar.d.ts +22 -14
  83. package/types/radix-ng-primitives-tooltip.d.ts +38 -14
@@ -1,6 +1,6 @@
1
1
  import * as _angular_core from '@angular/core';
2
- import { InjectionToken, Provider } from '@angular/core';
3
- import { BooleanInput } from '@radix-ng/primitives/core';
2
+ import { InjectionToken, Provider, Signal } from '@angular/core';
3
+ import { RdxFloatingTree, BooleanInput } from '@radix-ng/primitives/core';
4
4
  import * as i1 from '@radix-ng/primitives/focus-scope';
5
5
 
6
6
  /**
@@ -9,25 +9,25 @@ import * as i1 from '@radix-ng/primitives/focus-scope';
9
9
  * (Base UI keys `preferPreviousFocus = openInteractionType == null` off exactly this).
10
10
  */
11
11
  type RdxInteractionType = 'mouse' | 'touch' | 'pen' | 'keyboard' | '' | null;
12
- /** A focus target: an element, a getter, or `null`. */
13
- type RdxFocusTarget = HTMLElement | (() => HTMLElement | null) | null;
12
+ /** A focus target: an element, a getter, `null`, or `undefined` from a policy callback. */
13
+ type RdxFocusTarget = HTMLElement | (() => HTMLElement | null) | null | undefined;
14
14
  /** `initialFocus` policy (ADR 0017 §2) — a target, `false`, or an open-interaction callback. */
15
15
  type RdxInitialFocus = RdxFocusTarget | false | ((openInteractionType: RdxInteractionType) => RdxFocusTarget | false);
16
16
  /** `returnFocus` policy (ADR 0017 §2) — a target/boolean or a callback receiving the **close** interaction type. */
17
- type RdxReturnFocus = RdxFocusTarget | boolean | ((closeInteractionType: RdxInteractionType) => RdxFocusTarget | boolean);
17
+ type RdxReturnFocus = RdxFocusTarget | boolean | ((closeInteractionType: RdxInteractionType) => RdxFocusTarget | boolean | undefined);
18
18
  /** Normalizes a DOM event into Base UI-like interaction intent for focus policy decisions. */
19
19
  declare function getInteractionTypeFromEvent(event?: Event): RdxInteractionType;
20
20
  /** Resolves an {@link RdxFocusTarget} (element | getter | null) to a concrete element. */
21
- declare function resolveFocusTarget(target: RdxFocusTarget): HTMLElement | null;
21
+ declare function resolveFocusTarget(target: RdxFocusTarget): HTMLElement | null | undefined;
22
22
  /**
23
23
  * Resolves an {@link RdxInitialFocus} policy against how the popup opened.
24
24
  */
25
- declare function resolveInitialFocus(policy: RdxInitialFocus, openInteractionType: RdxInteractionType): HTMLElement | null | false;
25
+ declare function resolveInitialFocus(policy: RdxInitialFocus, openInteractionType: RdxInteractionType): HTMLElement | null | false | undefined;
26
26
  /**
27
27
  * Resolves an {@link RdxReturnFocus} policy against how the popup closed. `false` = do not return focus;
28
28
  * `true` = the default (return to the previously-focused element); an element = return there.
29
29
  */
30
- declare function resolveReturnFocus(policy: RdxReturnFocus, closeInteractionType: RdxInteractionType): HTMLElement | boolean | null;
30
+ declare function resolveReturnFocus(policy: RdxReturnFocus, closeInteractionType: RdxInteractionType): HTMLElement | boolean | null | undefined;
31
31
  /**
32
32
  * DI seam for a **composing primitive** (Dialog / Popover / Menu) to drive the manager's gates from its
33
33
  * own root context instead of template-bound inputs (which a primitive cannot set). Each field falls
@@ -40,9 +40,18 @@ interface RdxFloatingFocusManagerConfig {
40
40
  closeOnFocusOut?: () => boolean;
41
41
  initialFocus?: () => RdxInitialFocus;
42
42
  returnFocus?: () => RdxReturnFocus;
43
+ restoreFocus?: () => boolean | 'popup';
44
+ previousFocusableElement?: () => RdxFocusTarget;
45
+ nextFocusableElement?: () => RdxFocusTarget;
46
+ beforeContentFocusGuardRef?: () => RdxFocusGuardRef | null | undefined;
47
+ externalTree?: () => RdxFloatingTree | null | undefined;
48
+ getInsideElements?: () => Array<Element | null | undefined>;
43
49
  openInteractionType?: () => RdxInteractionType;
44
50
  closeInteractionType?: () => RdxInteractionType;
45
51
  }
52
+ type RdxFocusGuardRef = ((element: HTMLSpanElement | null) => void) | {
53
+ set: (element: HTMLSpanElement | null) => void;
54
+ };
46
55
  declare const RDX_FLOATING_FOCUS_MANAGER_CONFIG: InjectionToken<RdxFloatingFocusManagerConfig>;
47
56
  /** Provides a {@link RdxFloatingFocusManagerConfig} for an enclosing primitive's focus manager. */
48
57
  declare function provideFloatingFocusManagerConfig(factory: () => RdxFloatingFocusManagerConfig): Provider;
@@ -61,8 +70,7 @@ declare function provideFloatingFocusManagerConfig(factory: () => RdxFloatingFoc
61
70
  * - `loop` is forwarded to `RdxFocusScope`.
62
71
  * - `initialFocus` / `returnFocus` are **orchestrated** here (the §2 policy contract, incl. the
63
72
  * interaction-type callback forms): `initialFocus` via the scope's `mountAutoFocus` hook, `returnFocus`
64
- * via the scope's `returnFocus` config seam (resolved at the scope's queued post-unmount frame). The
65
- * portal-focus bridge remains a later-phase dependency.
73
+ * via the scope's `returnFocus` config seam (resolved at the scope's queued post-unmount frame).
66
74
  */
67
75
  declare class RdxFloatingFocusManager {
68
76
  /** Manager active-ness (ADR 0017 §2): the popup is mounted **and** not hover-opened. */
@@ -75,9 +83,25 @@ declare class RdxFloatingFocusManager {
75
83
  */
76
84
  readonly inert: _angular_core.InputSignalWithTransform<boolean | undefined, BooleanInput>;
77
85
  /** Where focus goes when the popup opens (ADR 0017 §2). */
78
- readonly initialFocus: _angular_core.InputSignal<RdxInitialFocus | undefined>;
86
+ readonly initialFocus: _angular_core.InputSignal<RdxInitialFocus>;
79
87
  /** Where focus returns when the popup closes (ADR 0017 §2). */
80
- readonly returnFocus: _angular_core.InputSignal<RdxReturnFocus | undefined>;
88
+ readonly returnFocus: _angular_core.InputSignal<RdxReturnFocus>;
89
+ /**
90
+ * Restores focus inside the floating tree when the currently focused inside element is removed and
91
+ * the browser drops focus onto `<body>` (Base UI `restoreFocus`). `true` restores to the last
92
+ * available tabbable candidate, `'popup'` restores to the popup container.
93
+ */
94
+ readonly restoreFocus: _angular_core.InputSignal<boolean | "popup" | undefined>;
95
+ /** Overrides where backward tabbing out of a non-modal portaled popup lands. */
96
+ readonly previousFocusableElement: _angular_core.InputSignal<RdxFocusTarget>;
97
+ /** Overrides where forward tabbing out of a non-modal portaled popup lands. */
98
+ readonly nextFocusableElement: _angular_core.InputSignal<RdxFocusTarget>;
99
+ /** Optional callback/signal that receives the leading content focus guard. */
100
+ readonly beforeContentFocusGuardRef: _angular_core.InputSignal<RdxFocusGuardRef | null | undefined>;
101
+ /** Explicit floating tree for detached sibling composition (Base UI `externalTree`). */
102
+ readonly externalTree: _angular_core.InputSignal<RdxFloatingTree | null | undefined>;
103
+ /** Additional elements treated as inside the floating subtree (Base UI `getInsideElements`). */
104
+ readonly getInsideElements: _angular_core.InputSignal<(() => Array<Element | null | undefined>) | undefined>;
81
105
  /**
82
106
  * Whether a **non-modal** popup closes when focus leaves to an unrelated node (Base UI
83
107
  * `closeOnFocusOut`, default `true`; Dialog sets it to `!disablePointerDismissal`). Modal popups
@@ -98,7 +122,13 @@ declare class RdxFloatingFocusManager {
98
122
  readonly effectiveInert: _angular_core.Signal<boolean>;
99
123
  readonly effectiveCloseOnFocusOut: _angular_core.Signal<boolean>;
100
124
  readonly effectiveInitialFocus: _angular_core.Signal<false | HTMLElement | ((openInteractionType: RdxInteractionType) => RdxFocusTarget | false) | null>;
101
- readonly effectiveReturnFocus: _angular_core.Signal<boolean | HTMLElement | ((closeInteractionType: RdxInteractionType) => RdxFocusTarget | boolean)>;
125
+ readonly effectiveReturnFocus: _angular_core.Signal<boolean | HTMLElement | ((closeInteractionType: RdxInteractionType) => RdxFocusTarget | boolean | undefined)>;
126
+ readonly effectiveRestoreFocus: _angular_core.Signal<boolean | "popup">;
127
+ readonly effectivePreviousFocusableElement: _angular_core.Signal<RdxFocusTarget>;
128
+ readonly effectiveNextFocusableElement: _angular_core.Signal<RdxFocusTarget>;
129
+ readonly effectiveBeforeContentFocusGuardRef: _angular_core.Signal<RdxFocusGuardRef | null | undefined>;
130
+ readonly effectiveExternalTree: _angular_core.Signal<RdxFloatingTree | null>;
131
+ readonly insideElements: _angular_core.Signal<Element[]>;
102
132
  readonly effectiveOpenInteractionType: _angular_core.Signal<RdxInteractionType>;
103
133
  readonly effectiveCloseInteractionType: _angular_core.Signal<RdxInteractionType>;
104
134
  /** The effective trap state the composed `RdxFocusScope` reads via its config token. */
@@ -155,6 +185,17 @@ declare class RdxFloatingFocusManager {
155
185
  * `FloatingFocusManager` `!modal` branch (`movedToUnrelatedNode`).
156
186
  */
157
187
  private wireCloseOnFocusOut;
188
+ /**
189
+ * Restore focus when an inside focused element disappears and the document focus falls back to
190
+ * `<body>`. This mirrors the practical Base UI `restoreFocus` path used by Select while keeping the
191
+ * broader portal-guard navigation separate.
192
+ */
193
+ private wireRestoreFocus;
194
+ /**
195
+ * Portal focus bridge (Base UI inside guards): when focus reaches the hidden guards around portaled
196
+ * content, redirect it either back inside the popup or to the configured neighboring tabbable node.
197
+ */
198
+ private wirePortalFocusBridge;
158
199
  /**
159
200
  * The marker keep-set is intentionally narrow: the popup/focus host only. Own sibling roots such as a
160
201
  * user backdrop are DOM-footprint bookkeeping, not marker keep-set members.
@@ -164,12 +205,68 @@ declare class RdxFloatingFocusManager {
164
205
  /** Whether `relatedTarget` is inside the popup, its trigger(s), or an ancestor / descendant popup. */
165
206
  private isRelatedTargetInside;
166
207
  private contextContains;
208
+ private currentFloatingNode;
209
+ private getTabbableContent;
210
+ private portalFocusContainer;
211
+ private defaultPreviousFocusable;
212
+ private defaultNextFocusable;
213
+ private setBeforeContentFocusGuardRef;
214
+ private isFromOutsideFocusGuard;
167
215
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxFloatingFocusManager, never>;
168
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFloatingFocusManager, "[rdxFloatingFocusManager]", ["rdxFloatingFocusManager"], { "enabled": { "alias": "enabled"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "inert": { "alias": "inert"; "required": false; "isSignal": true; }; "initialFocus": { "alias": "initialFocus"; "required": false; "isSignal": true; }; "returnFocus": { "alias": "returnFocus"; "required": false; "isSignal": true; }; "closeOnFocusOut": { "alias": "closeOnFocusOut"; "required": false; "isSignal": true; }; }, { "focusOut": "focusOut"; }, never, never, true, [{ directive: typeof i1.RdxFocusScope; inputs: { "loop": "loop"; }; outputs: {}; }]>;
216
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxFloatingFocusManager, "[rdxFloatingFocusManager]", ["rdxFloatingFocusManager"], { "enabled": { "alias": "enabled"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "inert": { "alias": "inert"; "required": false; "isSignal": true; }; "initialFocus": { "alias": "initialFocus"; "required": false; "isSignal": true; }; "returnFocus": { "alias": "returnFocus"; "required": false; "isSignal": true; }; "restoreFocus": { "alias": "restoreFocus"; "required": false; "isSignal": true; }; "previousFocusableElement": { "alias": "previousFocusableElement"; "required": false; "isSignal": true; }; "nextFocusableElement": { "alias": "nextFocusableElement"; "required": false; "isSignal": true; }; "beforeContentFocusGuardRef": { "alias": "beforeContentFocusGuardRef"; "required": false; "isSignal": true; }; "externalTree": { "alias": "externalTree"; "required": false; "isSignal": true; }; "getInsideElements": { "alias": "getInsideElements"; "required": false; "isSignal": true; }; "closeOnFocusOut": { "alias": "closeOnFocusOut"; "required": false; "isSignal": true; }; }, { "focusOut": "focusOut"; }, never, never, true, [{ directive: typeof i1.RdxFocusScope; inputs: { "loop": "loop"; }; outputs: {}; }]>;
169
217
  }
170
218
 
171
219
  /** The neutral "outside the active floating layer" marker (Base UI `data-base-ui-inert`). */
172
220
  declare const RDX_FLOATING_MARKER = "data-rdx-floating-inert";
173
221
 
174
- export { RDX_FLOATING_FOCUS_MANAGER_CONFIG, RDX_FLOATING_MARKER, RdxFloatingFocusManager, getInteractionTypeFromEvent, provideFloatingFocusManagerConfig, resolveFocusTarget, resolveInitialFocus, resolveReturnFocus };
175
- export type { RdxFloatingFocusManagerConfig, RdxFocusTarget, RdxInitialFocus, RdxInteractionType, RdxReturnFocus };
222
+ interface RdxTriggerInteractionOptions {
223
+ trigger: () => HTMLElement;
224
+ open: () => boolean;
225
+ activeTrigger?: () => HTMLElement | null | undefined;
226
+ disabled?: () => boolean;
227
+ contentId?: () => string | null | undefined;
228
+ }
229
+ interface RdxTriggerInteraction {
230
+ readonly lastPointerType: Signal<string>;
231
+ readonly isActive: Signal<boolean>;
232
+ readonly isInactive: Signal<boolean>;
233
+ readonly dataState: Signal<'open' | 'closed'>;
234
+ readonly dataPopupOpen: Signal<'' | undefined>;
235
+ readonly ariaControls: Signal<string | undefined>;
236
+ readonly ariaExpanded: Signal<boolean>;
237
+ readonly disabled: Signal<boolean>;
238
+ recordPointerDown: (event: PointerEvent) => void;
239
+ clickInteractionType: (event: MouseEvent) => RdxInteractionType;
240
+ }
241
+ interface RdxTriggerFocusGuardOptions {
242
+ trigger: () => HTMLElement;
243
+ close: (event: FocusEvent) => void;
244
+ beforeContentFocusGuard?: () => HTMLElement | null | undefined;
245
+ contentId?: () => string | null | undefined;
246
+ enabled?: () => boolean;
247
+ popupElement?: () => HTMLElement | null | undefined;
248
+ }
249
+ interface RdxTriggerFocusGuardAnchorOptions {
250
+ trigger: () => HTMLElement;
251
+ contentId: () => string | null | undefined;
252
+ enabled?: () => boolean;
253
+ }
254
+ /**
255
+ * Shared trigger state for floating primitives. It intentionally stays small: each primitive still owns
256
+ * its open/close business rules, while this layer normalizes active-trigger state and the open method
257
+ * signal that must be captured before the popup/focus manager mounts.
258
+ */
259
+ declare function createRdxTriggerInteraction(options: RdxTriggerInteractionOptions): RdxTriggerInteraction;
260
+ /**
261
+ * Adds Base UI's trigger-side focus guards for portaled content. The content guards remain owned by
262
+ * `RdxFloatingFocusManager`; these guards bridge tab order from the trigger into the portal and close the
263
+ * popup when focus leaves past either trigger-side boundary.
264
+ */
265
+ declare function useTriggerFocusGuards(options: RdxTriggerFocusGuardOptions): void;
266
+ /**
267
+ * Backwards-compatible aria-owns-only bridge for modal popups that do not need trigger-side tab guards.
268
+ */
269
+ declare function useTriggerFocusGuardAnchor(options: RdxTriggerFocusGuardAnchorOptions): void;
270
+
271
+ export { RDX_FLOATING_FOCUS_MANAGER_CONFIG, RDX_FLOATING_MARKER, RdxFloatingFocusManager, createRdxTriggerInteraction, getInteractionTypeFromEvent, provideFloatingFocusManagerConfig, resolveFocusTarget, resolveInitialFocus, resolveReturnFocus, useTriggerFocusGuardAnchor, useTriggerFocusGuards };
272
+ export type { RdxFloatingFocusManagerConfig, RdxFocusGuardRef, RdxFocusTarget, RdxInitialFocus, RdxInteractionType, RdxReturnFocus, RdxTriggerFocusGuardAnchorOptions, RdxTriggerFocusGuardOptions, RdxTriggerInteraction, RdxTriggerInteractionOptions };
@@ -2,11 +2,12 @@ import * as _angular_core from '@angular/core';
2
2
  import { Signal, WritableSignal } from '@angular/core';
3
3
  import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
4
4
  import { RdxFloatingRootContext, BooleanInput, Direction, RdxCancelableChangeEventDetails, NumberInput } from '@radix-ng/primitives/core';
5
- import * as i3 from '@radix-ng/primitives/floating-focus-manager';
5
+ import * as _radix_ng_primitives_floating_focus_manager from '@radix-ng/primitives/floating-focus-manager';
6
6
  import { RdxInteractionType } from '@radix-ng/primitives/floating-focus-manager';
7
7
  import * as i1 from '@radix-ng/primitives/popper';
8
8
  import { RdxPopperContentWrapper } from '@radix-ng/primitives/popper';
9
9
  import * as _radix_ng_primitives_menu from '@radix-ng/primitives/menu';
10
+ import * as i2 from '@radix-ng/primitives/composite';
10
11
  import * as i1$1 from '@radix-ng/primitives/portal';
11
12
  import { RdxOutsidePressDomEvent } from '@radix-ng/primitives/dismissable-layer';
12
13
 
@@ -71,6 +72,7 @@ interface RdxMenuRootContext {
71
72
  trigger: Signal<HTMLElement | undefined>;
72
73
  /** The popup element, once mounted. Used by submenu safe-polygon geometry. */
73
74
  popupElement: Signal<HTMLElement | undefined>;
75
+ beforeContentFocusGuard: Signal<HTMLElement | null>;
74
76
  transitionStatus: Signal<RdxMenuTransitionStatus>;
75
77
  close: (reason?: RdxMenuOpenChangeReason, event?: Event) => void;
76
78
  /** Close this menu and every ancestor — used by item selection (the whole menu dismisses). */
@@ -81,6 +83,7 @@ interface RdxMenuRootContext {
81
83
  showWithoutAutoFocus: (reason?: RdxMenuOpenChangeReason, event?: Event) => void;
82
84
  registerTrigger: (el: HTMLElement) => () => void;
83
85
  registerPopup: (el: HTMLElement) => () => void;
86
+ setBeforeContentFocusGuard: (element: HTMLElement | null) => void;
84
87
  registerTransitionElement: (element: HTMLElement) => () => void;
85
88
  registerPopupArrowNavigationHandler: (handler: (offset: 1 | -1) => boolean) => () => void;
86
89
  registerTriggerInteractionHandler: (handler: RdxMenuTriggerInteractionHandler) => () => void;
@@ -174,6 +177,7 @@ declare class RdxMenuRoot {
174
177
  readonly onOpenChangeComplete: _angular_core.OutputEmitterRef<boolean>;
175
178
  readonly trigger: _angular_core.WritableSignal<HTMLElement | undefined>;
176
179
  readonly popupElement: _angular_core.WritableSignal<HTMLElement | undefined>;
180
+ readonly beforeContentFocusGuard: _angular_core.WritableSignal<HTMLElement | null>;
177
181
  readonly transitionStatus: Signal<_radix_ng_primitives_core.RdxTransitionStatus>;
178
182
  /** Whether the popup grabs focus when it opens. Set false for menubar hover-switching. */
179
183
  readonly autoFocus: _angular_core.WritableSignal<RdxMenuAutoFocus>;
@@ -214,6 +218,7 @@ declare class RdxMenuRoot {
214
218
  closeEntireMenu(reason?: RdxMenuOpenChangeReason, event?: Event): void;
215
219
  registerTrigger(el: HTMLElement): () => void;
216
220
  registerPopup(el: HTMLElement): () => void;
221
+ setBeforeContentFocusGuard(element: HTMLElement | null): void;
217
222
  registerTransitionElement(element: HTMLElement): () => void;
218
223
  registerPopupArrowNavigationHandler(handler: (offset: 1 | -1) => boolean): () => void;
219
224
  handlePopupArrowNavigation(offset: 1 | -1): boolean;
@@ -222,6 +227,7 @@ declare class RdxMenuRoot {
222
227
  markAsSubmenu(): void;
223
228
  closeParent(): void;
224
229
  private createOpenChangeEvent;
230
+ private focusOpenPopup;
225
231
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxMenuRoot, never>;
226
232
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenuRoot, "[rdxMenuRoot],[rdxMenuSubmenuRoot]", ["rdxMenuRoot"], { "open": { "alias": "open"; "required": false; "isSignal": true; }; "defaultOpen": { "alias": "defaultOpen"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "modal": { "alias": "modal"; "required": false; "isSignal": true; }; "loopFocus": { "alias": "loopFocus"; "required": false; "isSignal": true; }; "highlightItemOnHover": { "alias": "highlightItemOnHover"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "dirInput": { "alias": "dir"; "required": false; "isSignal": true; }; "closeParentOnEsc": { "alias": "closeParentOnEsc"; "required": false; "isSignal": true; }; }, { "open": "openChange"; "onOpenChange": "onOpenChange"; "onOpenChangeComplete": "onOpenChangeComplete"; }, never, never, true, [{ directive: typeof i1.RdxPopper; inputs: {}; outputs: {}; }]>;
227
233
  }
@@ -253,8 +259,10 @@ declare class RdxMenuTrigger {
253
259
  readonly closeDelay: _angular_core.InputSignalWithTransform<number | undefined, NumberInput>;
254
260
  protected readonly nativeButtonState: _angular_core.Signal<boolean>;
255
261
  protected readonly isDisabled: _angular_core.Signal<boolean>;
262
+ protected readonly triggerInteraction: _radix_ng_primitives_floating_focus_manager.RdxTriggerInteraction;
256
263
  constructor();
257
264
  protected handleMouseDown(event: MouseEvent): void;
265
+ protected handlePointerDown(event: PointerEvent): void;
258
266
  protected handleClick(event: MouseEvent): void;
259
267
  protected handleArrowDown(event: Event): void;
260
268
  protected handleArrowUp(event: Event): void;
@@ -274,7 +282,7 @@ declare class RdxMenuTrigger {
274
282
  private clearMouseUpGuard;
275
283
  private restoreKeyboardPopupFocus;
276
284
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxMenuTrigger, never>;
277
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenuTrigger, "[rdxMenuTrigger]", ["rdxMenuTrigger"], { "nativeButton": { "alias": "nativeButton"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "openOnHover": { "alias": "openOnHover"; "required": false; "isSignal": true; }; "delay": { "alias": "delay"; "required": false; "isSignal": true; }; "closeDelay": { "alias": "closeDelay"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.RdxPopperAnchor; inputs: {}; outputs: {}; }]>;
285
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenuTrigger, "[rdxMenuTrigger]", ["rdxMenuTrigger"], { "nativeButton": { "alias": "nativeButton"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "openOnHover": { "alias": "openOnHover"; "required": false; "isSignal": true; }; "delay": { "alias": "delay"; "required": false; "isSignal": true; }; "closeDelay": { "alias": "closeDelay"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.RdxPopperAnchor; inputs: {}; outputs: {}; }, { directive: typeof i2.RdxCompositeItem; inputs: {}; outputs: {}; }]>;
278
286
  }
279
287
 
280
288
  /**
@@ -384,7 +392,7 @@ declare class RdxMenuPopup {
384
392
  private readonly elementRef;
385
393
  private search;
386
394
  private searchTimer;
387
- protected readonly align: _angular_core.Signal<"end" | "start" | "center" | undefined>;
395
+ protected readonly align: _angular_core.Signal<"center" | "end" | "start" | undefined>;
388
396
  protected readonly side: _angular_core.Signal<"top" | "right" | "bottom" | "left" | undefined>;
389
397
  /**
390
398
  * Event handler called when the escape key is pressed. Can be prevented.
@@ -416,7 +424,7 @@ declare class RdxMenuPopup {
416
424
  private scheduleSubmenuKeyboardFocus;
417
425
  private applySubmenuKeyboardFocus;
418
426
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxMenuPopup, never>;
419
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenuPopup, "[rdxMenuPopup]", ["rdxMenuPopup"], {}, { "escapeKeyDown": "escapeKeyDown"; "pointerDownOutside": "pointerDownOutside"; "focusOutside": "focusOutside"; "interactOutside": "interactOutside"; "openAutoFocus": "openAutoFocus"; "closeAutoFocus": "closeAutoFocus"; }, never, never, true, [{ directive: typeof i1.RdxPopperContent; inputs: {}; outputs: {}; }, { directive: typeof _radix_ng_primitives_core.RdxFloatingNodeRegistration; inputs: {}; outputs: {}; }, { directive: typeof i3.RdxFloatingFocusManager; inputs: {}; outputs: {}; }]>;
427
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenuPopup, "[rdxMenuPopup]", ["rdxMenuPopup"], {}, { "escapeKeyDown": "escapeKeyDown"; "pointerDownOutside": "pointerDownOutside"; "focusOutside": "focusOutside"; "interactOutside": "interactOutside"; "openAutoFocus": "openAutoFocus"; "closeAutoFocus": "closeAutoFocus"; }, never, never, true, [{ directive: typeof i1.RdxPopperContent; inputs: {}; outputs: {}; }, { directive: typeof _radix_ng_primitives_core.RdxFloatingNodeRegistration; inputs: {}; outputs: {}; }, { directive: typeof _radix_ng_primitives_floating_focus_manager.RdxFloatingFocusManager; inputs: {}; outputs: {}; }]>;
420
428
  }
421
429
 
422
430
  /**
@@ -470,7 +478,7 @@ declare class RdxMenuArrow {
470
478
  protected readonly rootContext: _radix_ng_primitives_menu.RdxMenuRootContext;
471
479
  private readonly wrapper;
472
480
  protected readonly side: _angular_core.Signal<"top" | "right" | "bottom" | "left" | undefined>;
473
- protected readonly align: _angular_core.Signal<"end" | "start" | "center" | undefined>;
481
+ protected readonly align: _angular_core.Signal<"center" | "end" | "start" | undefined>;
474
482
  protected readonly uncentered: _angular_core.Signal<boolean>;
475
483
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxMenuArrow, never>;
476
484
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenuArrow, "[rdxMenuArrow]", ["rdxMenuArrow"], {}, {}, never, never, true, [{ directive: typeof i1.RdxPopperArrow; inputs: {}; outputs: {}; }]>;
@@ -2,6 +2,7 @@ import * as _angular_core from '@angular/core';
2
2
  import { Signal } from '@angular/core';
3
3
  import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
4
4
  import { BooleanInput } from '@radix-ng/primitives/core';
5
+ import * as i1 from '@radix-ng/primitives/composite';
5
6
 
6
7
  type RdxMenubarOrientation = 'horizontal' | 'vertical';
7
8
  interface RdxMenubarContext {
@@ -22,9 +23,12 @@ declare const provideRdxMenubarContext: (useFactory: () => RdxMenubarContext) =>
22
23
  * Coordinates open/close state across multiple menus and provides arrow-key navigation.
23
24
  */
24
25
  declare class RdxMenubarRoot {
26
+ private readonly elementRef;
27
+ private readonly compositeRoot;
25
28
  private readonly menuRoots;
26
29
  private readonly ids;
27
30
  private items;
31
+ private readonly itemsVersion;
28
32
  /** Whether every menubar trigger is disabled. */
29
33
  readonly disabled: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
30
34
  /** Whether arrow-key navigation wraps at the first/last trigger. */
@@ -46,15 +50,16 @@ declare class RdxMenubarRoot {
46
50
  private handleTriggerArrow;
47
51
  private handleTriggerBoundary;
48
52
  focusAdjacent(currentId: string, offset: 1 | -1, openOnMove: boolean): void;
49
- protected handleArrowLeft(event: Event): void;
50
- protected handleArrowRight(event: Event): void;
51
- private handleOpenMenuNavigation;
52
53
  private focusItem;
53
- private updateTriggerTabStops;
54
+ protected handleFocusIn(event: FocusEvent): void;
55
+ private highlightItem;
54
56
  private enabledItems;
55
57
  private hasOpenMenu;
58
+ private sortItems;
59
+ private markItemsChanged;
60
+ private syncDisabledIndices;
56
61
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxMenubarRoot, never>;
57
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenubarRoot, "[rdxMenubarRoot]", ["rdxMenubarRoot"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "loopFocus": { "alias": "loopFocus"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; }, {}, ["menuRoots"], never, true, never>;
62
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxMenubarRoot, "[rdxMenubarRoot]", ["rdxMenubarRoot"], { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "loopFocus": { "alias": "loopFocus"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; }, {}, ["menuRoots"], never, true, [{ directive: typeof i1.RdxCompositeRoot; inputs: {}; outputs: {}; }]>;
58
63
  }
59
64
 
60
65
  declare class RdxMenubarModule {
@@ -2,17 +2,17 @@ import * as _angular_core from '@angular/core';
2
2
  import { TemplateRef, Signal } from '@angular/core';
3
3
  import * as i1 from '@radix-ng/primitives/portal';
4
4
  import * as _radix_ng_primitives_core from '@radix-ng/primitives/core';
5
- import { RdxCancelableChangeEventDetails, RdxTransitionStatus, RdxFloatingRootContext, BooleanInput, NumberInput } from '@radix-ng/primitives/core';
5
+ import { RdxCancelableChangeEventDetails, RdxTransitionStatus, RdxFloatingRootContext, NumberInput } from '@radix-ng/primitives/core';
6
6
  import * as i1$1 from '@radix-ng/primitives/popper';
7
7
  import { RdxPopperContentWrapper } from '@radix-ng/primitives/popper';
8
8
  import * as _radix_ng_primitives_navigation_menu from '@radix-ng/primitives/navigation-menu';
9
- import * as i1$2 from '@radix-ng/primitives/roving-focus';
9
+ import * as i1$2 from '@radix-ng/primitives/composite';
10
10
  import { RdxOutsidePressDomEvent } from '@radix-ng/primitives/dismissable-layer';
11
11
 
12
12
  /**
13
13
  * Structural directive that teleports the navigation menu popup into a container (default
14
14
  * `document.body`) while the menu is open, and keeps it mounted until any CSS exit `@keyframes`
15
- * finishes.
15
+ * finishes. Set `[keepMounted]="true"` to keep the portal mounted while closed.
16
16
  *
17
17
  * Apply it with the `*` microsyntax on the positioner —
18
18
  * `<div *rdxNavigationMenuPortal rdxNavigationMenuPositioner>` — or as an explicit
@@ -20,8 +20,14 @@ import { RdxOutsidePressDomEvent } from '@radix-ng/primitives/dismissable-layer'
20
20
  * `[container]`.
21
21
  */
22
22
  declare class RdxNavigationMenuPortal {
23
+ private readonly rootContext;
24
+ /**
25
+ * Keep the portal mounted while the menu is closed.
26
+ */
27
+ readonly keepMounted: _angular_core.InputSignalWithTransform<boolean, unknown>;
28
+ readonly present: _angular_core.Signal<boolean>;
23
29
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuPortal, never>;
24
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuPortal, "ng-template[rdxNavigationMenuPortal]", ["rdxNavigationMenuPortal"], {}, {}, never, never, true, [{ directive: typeof i1.RdxPortalPresence; inputs: { "container": "container"; }; outputs: {}; }]>;
30
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuPortal, "ng-template[rdxNavigationMenuPortal]", ["rdxNavigationMenuPortal"], { "keepMounted": { "alias": "keepMounted"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1.RdxPortalPresence; inputs: { "container": "container"; }; outputs: {}; }]>;
25
31
  }
26
32
  /**
27
33
  * Dev-mode guard: `rdxNavigationMenuPortal` used to be an attribute directive on a `<div>`. It is now
@@ -36,7 +42,7 @@ declare class RdxNavigationMenuPortalMisuseGuard {
36
42
 
37
43
  type NavigationMenuOrientation = 'horizontal' | 'vertical';
38
44
  type NavigationMenuDirection = 'ltr' | 'rtl';
39
- type RdxNavigationMenuOpenChangeReason = 'trigger-hover' | 'trigger-focus' | 'trigger-press' | 'list-navigation' | 'outside-press' | 'focus-out' | 'escape-key' | 'link-select' | 'list-leave' | 'none';
45
+ type RdxNavigationMenuOpenChangeReason = 'trigger-hover' | 'trigger-press' | 'list-navigation' | 'outside-press' | 'focus-out' | 'escape-key' | 'link-select' | 'list-leave' | 'none';
40
46
  type RdxNavigationMenuOpenChangeEventDetails = RdxCancelableChangeEventDetails<RdxNavigationMenuOpenChangeReason>;
41
47
  interface RdxNavigationMenuOpenChange {
42
48
  value: string | null;
@@ -62,7 +68,6 @@ interface RdxNavigationMenuRootContext {
62
68
  readonly baseId: string;
63
69
  readonly orientation: Signal<NavigationMenuOrientation>;
64
70
  readonly dir: Signal<NavigationMenuDirection>;
65
- readonly loop: Signal<boolean>;
66
71
  /** Value of the currently open item, or `null` when closed. */
67
72
  readonly value: Signal<string | null>;
68
73
  /** Value of the previously open item (used for slide-direction morphing). */
@@ -74,7 +79,14 @@ interface RdxNavigationMenuRootContext {
74
79
  /** The active trigger element the popup is anchored to. */
75
80
  readonly trigger: Signal<HTMLElement | undefined>;
76
81
  readonly triggers: Signal<HTMLElement[]>;
82
+ readonly list: Signal<HTMLElement | undefined>;
83
+ readonly contents: Signal<Map<string, RdxNavigationMenuContentEntry>>;
77
84
  readonly activeContent: Signal<RdxNavigationMenuContentEntry | undefined>;
85
+ readonly popup: Signal<HTMLElement | undefined>;
86
+ readonly size: Signal<{
87
+ width: number;
88
+ height: number;
89
+ } | null>;
78
90
  contentId(value: string): string;
79
91
  triggerId(value: string): string;
80
92
  setValue(value: string | null, reason?: RdxNavigationMenuOpenChangeReason, event?: Event): void;
@@ -85,8 +97,14 @@ interface RdxNavigationMenuRootContext {
85
97
  closeOnHover(event?: PointerEvent): void;
86
98
  cancelHoverOpen(): void;
87
99
  cancelHoverClose(): void;
100
+ setSize(size: {
101
+ width: number;
102
+ height: number;
103
+ } | null): void;
88
104
  registerTrigger(value: string, trigger: HTMLElement): () => void;
105
+ registerList(list: HTMLElement): () => void;
89
106
  registerContent(entry: RdxNavigationMenuContentEntry): () => void;
107
+ registerPopup(element: HTMLElement): () => void;
90
108
  registerTransitionElement(element: HTMLElement): () => void;
91
109
  registerViewport(onTriggerChange: (previous: HTMLElement, next: HTMLElement) => void): () => void;
92
110
  }
@@ -127,10 +145,6 @@ declare class RdxNavigationMenuRoot {
127
145
  */
128
146
  readonly dirInput: _angular_core.InputSignal<NavigationMenuDirection | undefined>;
129
147
  readonly dir: _angular_core.Signal<_radix_ng_primitives_core.Direction>;
130
- /**
131
- * Whether keyboard navigation loops from the last item back to the first and vice versa.
132
- */
133
- readonly loop: _angular_core.InputSignalWithTransform<boolean, BooleanInput>;
134
148
  /**
135
149
  * How long to wait before opening the menu on hover, in milliseconds.
136
150
  */
@@ -164,7 +178,13 @@ declare class RdxNavigationMenuRoot {
164
178
  readonly present: _angular_core.Signal<boolean>;
165
179
  readonly trigger: _angular_core.WritableSignal<HTMLElement | undefined>;
166
180
  readonly triggers: _angular_core.WritableSignal<HTMLElement[]>;
181
+ readonly list: _angular_core.WritableSignal<HTMLElement | undefined>;
167
182
  readonly contents: _angular_core.WritableSignal<Map<string, RdxNavigationMenuContentEntry>>;
183
+ readonly popup: _angular_core.WritableSignal<HTMLElement | undefined>;
184
+ readonly size: _angular_core.WritableSignal<{
185
+ width: number;
186
+ height: number;
187
+ } | null>;
168
188
  readonly activeContent: _angular_core.Signal<RdxNavigationMenuContentEntry | undefined>;
169
189
  private readonly registeredTriggers;
170
190
  private readonly viewportTriggerChange;
@@ -180,7 +200,13 @@ declare class RdxNavigationMenuRoot {
180
200
  cancelHoverOpen(): void;
181
201
  cancelHoverClose(): void;
182
202
  registerTrigger(value: string, trigger: HTMLElement): () => void;
203
+ registerList(list: HTMLElement): () => void;
183
204
  registerContent(entry: RdxNavigationMenuContentEntry): () => void;
205
+ registerPopup(element: HTMLElement): () => void;
206
+ setSize(size: {
207
+ width: number;
208
+ height: number;
209
+ } | null): void;
184
210
  registerTransitionElement(element: HTMLElement): () => void;
185
211
  registerViewport(onTriggerChange: (previous: HTMLElement, next: HTMLElement) => void): () => boolean;
186
212
  private createOpenChangeEvent;
@@ -190,19 +216,20 @@ declare class RdxNavigationMenuRoot {
190
216
  private clearCloseTimer;
191
217
  private isInsideOpenChild;
192
218
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuRoot, never>;
193
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuRoot, "[rdxNavigationMenuRoot]", ["rdxNavigationMenuRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "defaultValue": { "alias": "defaultValue"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "dirInput": { "alias": "dir"; "required": false; "isSignal": true; }; "loop": { "alias": "loop"; "required": false; "isSignal": true; }; "delay": { "alias": "delay"; "required": false; "isSignal": true; }; "closeDelay": { "alias": "closeDelay"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onValueChange": "onValueChange"; "onOpenChange": "onOpenChange"; "onOpenChangeComplete": "onOpenChangeComplete"; }, never, never, true, [{ directive: typeof i1$1.RdxPopper; inputs: {}; outputs: {}; }, { directive: typeof _radix_ng_primitives_core.RdxFloatingNodeRegistration; inputs: {}; outputs: {}; }]>;
219
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuRoot, "[rdxNavigationMenuRoot]", ["rdxNavigationMenuRoot"], { "value": { "alias": "value"; "required": false; "isSignal": true; }; "defaultValue": { "alias": "defaultValue"; "required": false; "isSignal": true; }; "orientation": { "alias": "orientation"; "required": false; "isSignal": true; }; "dirInput": { "alias": "dir"; "required": false; "isSignal": true; }; "delay": { "alias": "delay"; "required": false; "isSignal": true; }; "closeDelay": { "alias": "closeDelay"; "required": false; "isSignal": true; }; }, { "value": "valueChange"; "onValueChange": "onValueChange"; "onOpenChange": "onOpenChange"; "onOpenChangeComplete": "onOpenChangeComplete"; }, never, never, true, [{ directive: typeof i1$1.RdxPopper; inputs: {}; outputs: {}; }, { directive: typeof _radix_ng_primitives_core.RdxFloatingNodeRegistration; inputs: {}; outputs: {}; }]>;
194
220
  }
195
221
 
196
222
  /**
197
- * Contains the navigation menu items. Renders as a menubar with roving keyboard focus.
223
+ * Contains the navigation menu items and coordinates composite keyboard focus between triggers.
198
224
  */
199
225
  declare class RdxNavigationMenuList {
200
226
  protected readonly rootContext: _radix_ng_primitives_navigation_menu.RdxNavigationMenuRootContext;
201
- private readonly rovingFocusGroup;
227
+ private readonly compositeRoot;
202
228
  constructor();
229
+ protected onKeydown(event: KeyboardEvent): void;
203
230
  protected onPointerLeave(event: PointerEvent): void;
204
231
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuList, never>;
205
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuList, "[rdxNavigationMenuList]", never, {}, {}, never, never, true, [{ directive: typeof i1$2.RdxRovingFocusGroupDirective; inputs: {}; outputs: {}; }]>;
232
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuList, "[rdxNavigationMenuList]", never, {}, {}, never, never, true, [{ directive: typeof i1$2.RdxCompositeRoot; inputs: {}; outputs: {}; }]>;
206
233
  }
207
234
 
208
235
  /**
@@ -229,8 +256,7 @@ declare class RdxNavigationMenuItem {
229
256
  */
230
257
  declare class RdxNavigationMenuTrigger {
231
258
  protected readonly item: RdxNavigationMenuItem;
232
- private readonly rootContext;
233
- private readonly rovingFocusItem;
259
+ protected readonly rootContext: _radix_ng_primitives_navigation_menu.RdxNavigationMenuRootContext;
234
260
  private readonly elementRef;
235
261
  private readonly document;
236
262
  /**
@@ -246,18 +272,12 @@ declare class RdxNavigationMenuTrigger {
246
272
  protected onClick(event: MouseEvent): void;
247
273
  protected onPointerEnter(event: PointerEvent): void;
248
274
  protected onPointerLeave(event: PointerEvent): void;
249
- /**
250
- * Open-follows-focus: while the menu is already open, moving keyboard focus (arrow keys via
251
- * roving) to another trigger switches the shared popup to that item — matching Base UI, so the
252
- * open menu visibly responds to arrow-key navigation. Focus never *opens* a closed menu.
253
- */
254
- protected onFocus(): void;
255
275
  protected onKeydown(event: KeyboardEvent): void;
256
276
  /** The key that moves focus from the trigger into the open content, based on orientation/dir. */
257
277
  private entryKey;
258
278
  private focusContent;
259
279
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuTrigger, never>;
260
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuTrigger, "button[rdxNavigationMenuTrigger]", never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "openOnHover": { "alias": "openOnHover"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1$2.RdxRovingFocusItemDirective; inputs: {}; outputs: {}; }]>;
280
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuTrigger, "button[rdxNavigationMenuTrigger]", never, { "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "openOnHover": { "alias": "openOnHover"; "required": false; "isSignal": true; }; }, {}, never, never, true, [{ directive: typeof i1$2.RdxCompositeItem; inputs: {}; outputs: {}; }]>;
261
281
  }
262
282
 
263
283
  /**
@@ -297,10 +317,10 @@ declare class RdxNavigationMenuContent {
297
317
  }
298
318
 
299
319
  /**
300
- * A navigation link. Closes the menu on selection unless prevented.
320
+ * A navigation link. Can close the menu on selection when `closeOnClick` is enabled.
301
321
  *
302
- * Used both as a top-level menubar item and inside content. It is a plain tabbable anchor (not part
303
- * of the menubar's arrow-key roving), matching Base UI.
322
+ * Used both as a top-level navigation item and inside content. Top-level links join the list's
323
+ * composite collection, matching Base UI's CompositeItem-backed NavigationMenu.Link.
304
324
  */
305
325
  declare class RdxNavigationMenuLink {
306
326
  private readonly rootContext;
@@ -320,7 +340,7 @@ declare class RdxNavigationMenuLink {
320
340
  protected onClick(event: Event): void;
321
341
  protected onKeydown(event: KeyboardEvent): void;
322
342
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuLink, never>;
323
- static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuLink, "[rdxNavigationMenuLink]", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "closeOnClick": { "alias": "closeOnClick"; "required": false; "isSignal": true; }; }, { "onSelect": "onSelect"; }, never, never, true, never>;
343
+ static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuLink, "[rdxNavigationMenuLink]", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "closeOnClick": { "alias": "closeOnClick"; "required": false; "isSignal": true; }; }, { "onSelect": "onSelect"; }, never, never, true, [{ directive: typeof i1$2.RdxCompositeItem; inputs: {}; outputs: {}; }]>;
324
344
  }
325
345
 
326
346
  /**
@@ -328,6 +348,7 @@ declare class RdxNavigationMenuLink {
328
348
  */
329
349
  declare class RdxNavigationMenuBackdrop {
330
350
  protected readonly rootContext: _radix_ng_primitives_navigation_menu.RdxNavigationMenuRootContext;
351
+ constructor();
331
352
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuBackdrop, never>;
332
353
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuBackdrop, "[rdxNavigationMenuBackdrop]", never, {}, {}, never, never, true, never>;
333
354
  }
@@ -362,8 +383,7 @@ declare class RdxNavigationMenuPopup {
362
383
  private readonly elementRef;
363
384
  protected readonly side: _angular_core.Signal<"top" | "right" | "bottom" | "left" | undefined>;
364
385
  protected readonly align: _angular_core.Signal<"start" | "center" | "end" | undefined>;
365
- /** Names the menu after the active trigger so the `role="menu"` element has an accessible name. */
366
- protected readonly labelledBy: _angular_core.Signal<string | undefined>;
386
+ protected readonly id: _angular_core.Signal<string>;
367
387
  /**
368
388
  * Event handler called when the escape key is down. Can be prevented.
369
389
  */
@@ -379,11 +399,15 @@ declare class RdxNavigationMenuPopup {
379
399
  constructor();
380
400
  protected onPointerLeave(event: PointerEvent): void;
381
401
  /**
382
- * Keyboard navigation inside the open panel: Down/Up move between the panel's focusable items in
383
- * DOM order, Home/End jump to the first/last, and Up from the first item returns focus to the
384
- * trigger. (Tab keeps working natively; Escape is handled by the dismissal capability.)
402
+ * Keyboard navigation inside the open panel mirrors Base UI's CompositeRoot-backed content:
403
+ * arrow keys move between panel focusables in DOM order, Home/End jump to the first/last, Up from
404
+ * the first item returns focus to the trigger, and Tab exits the portalled panel through the
405
+ * logical top-level navigation order. Escape is handled by the dismissal capability.
385
406
  */
386
407
  protected onKeydown(event: KeyboardEvent): void;
408
+ private handleTabKey;
409
+ private getNextTopLevelItem;
410
+ private getTopLevelItems;
387
411
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuPopup, never>;
388
412
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuPopup, "[rdxNavigationMenuPopup]", never, {}, { "escapeKeyDown": "escapeKeyDown"; "pointerDownOutside": "pointerDownOutside"; "focusOutside": "focusOutside"; }, never, never, true, [{ directive: typeof i1$1.RdxPopperContent; inputs: {}; outputs: {}; }]>;
389
413
  }
@@ -422,13 +446,21 @@ declare class RdxNavigationMenuViewport {
422
446
  height: number;
423
447
  } | null>;
424
448
  private current;
449
+ private readonly rendered;
425
450
  private previousElement;
426
451
  private pendingDirection;
427
452
  private cleanupTimer;
428
453
  private readonly resizeObserver;
429
454
  private readonly activeContent;
455
+ private readonly contents;
430
456
  constructor();
457
+ private sync;
431
458
  private render;
459
+ private createRendered;
460
+ private deactivateCurrent;
461
+ private markCurrent;
462
+ private markInactive;
463
+ private destroyRendered;
432
464
  private startLeave;
433
465
  private removePrevious;
434
466
  private clearCleanupTimer;
@@ -437,7 +469,7 @@ declare class RdxNavigationMenuViewport {
437
469
  static ɵdir: _angular_core.ɵɵDirectiveDeclaration<RdxNavigationMenuViewport, "[rdxNavigationMenuViewport]", never, { "forceMount": { "alias": "forceMount"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
438
470
  }
439
471
 
440
- declare const navigationMenuImports: (typeof RdxNavigationMenuPortal)[];
472
+ declare const navigationMenuImports: (typeof RdxNavigationMenuPortalMisuseGuard)[];
441
473
  declare class RdxNavigationMenuModule {
442
474
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<RdxNavigationMenuModule, never>;
443
475
  static ɵmod: _angular_core.ɵɵNgModuleDeclaration<RdxNavigationMenuModule, never, [typeof RdxNavigationMenuRoot, typeof RdxNavigationMenuList, typeof RdxNavigationMenuItem, typeof RdxNavigationMenuTrigger, typeof RdxNavigationMenuIcon, typeof RdxNavigationMenuContent, typeof RdxNavigationMenuLink, typeof RdxNavigationMenuPortal, typeof RdxNavigationMenuPortalMisuseGuard, typeof RdxNavigationMenuBackdrop, typeof RdxNavigationMenuPositioner, typeof RdxNavigationMenuPopup, typeof RdxNavigationMenuArrow, typeof RdxNavigationMenuViewport], [typeof RdxNavigationMenuRoot, typeof RdxNavigationMenuList, typeof RdxNavigationMenuItem, typeof RdxNavigationMenuTrigger, typeof RdxNavigationMenuIcon, typeof RdxNavigationMenuContent, typeof RdxNavigationMenuLink, typeof RdxNavigationMenuPortal, typeof RdxNavigationMenuPortalMisuseGuard, typeof RdxNavigationMenuBackdrop, typeof RdxNavigationMenuPositioner, typeof RdxNavigationMenuPopup, typeof RdxNavigationMenuArrow, typeof RdxNavigationMenuViewport]>;