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

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 (104) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +76 -6
  3. package/fesm2022/radix-ng-primitives-accordion.mjs +5 -3
  4. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  5. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +31 -24
  6. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
  7. package/fesm2022/radix-ng-primitives-autocomplete.mjs +1744 -0
  8. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -0
  9. package/fesm2022/radix-ng-primitives-calendar.mjs +5 -3
  10. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
  11. package/fesm2022/radix-ng-primitives-combobox.mjs +1399 -606
  12. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
  13. package/fesm2022/radix-ng-primitives-config.mjs +13 -4
  14. package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
  15. package/fesm2022/radix-ng-primitives-context-menu.mjs +51 -10
  16. package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
  17. package/fesm2022/radix-ng-primitives-core.mjs +1345 -64
  18. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  19. package/fesm2022/radix-ng-primitives-date-field.mjs +5 -3
  20. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  21. package/fesm2022/radix-ng-primitives-dialog.mjs +271 -145
  22. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  23. package/fesm2022/radix-ng-primitives-direction-provider.mjs +70 -0
  24. package/fesm2022/radix-ng-primitives-direction-provider.mjs.map +1 -0
  25. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +519 -184
  26. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
  27. package/fesm2022/radix-ng-primitives-drawer.mjs +154 -64
  28. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
  29. package/fesm2022/radix-ng-primitives-field.mjs +3 -2
  30. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
  31. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +517 -0
  32. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -0
  33. package/fesm2022/radix-ng-primitives-focus-scope.mjs +296 -70
  34. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  35. package/fesm2022/radix-ng-primitives-menu.mjs +894 -299
  36. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  37. package/fesm2022/radix-ng-primitives-menubar.mjs +32 -4
  38. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  39. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +176 -207
  40. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  41. package/fesm2022/radix-ng-primitives-popover.mjs +250 -250
  42. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  43. package/fesm2022/radix-ng-primitives-popper.mjs +94 -45
  44. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  45. package/fesm2022/radix-ng-primitives-portal.mjs +107 -17
  46. package/fesm2022/radix-ng-primitives-portal.mjs.map +1 -1
  47. package/fesm2022/radix-ng-primitives-presence.mjs +262 -79
  48. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  49. package/fesm2022/radix-ng-primitives-preview-card.mjs +172 -218
  50. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
  51. package/fesm2022/radix-ng-primitives-roving-focus.mjs +4 -2
  52. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  53. package/fesm2022/radix-ng-primitives-scroll-area.mjs +5 -4
  54. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  55. package/fesm2022/radix-ng-primitives-select.mjs +303 -234
  56. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  57. package/fesm2022/radix-ng-primitives-slider.mjs +5 -3
  58. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  59. package/fesm2022/radix-ng-primitives-stepper.mjs +5 -3
  60. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  61. package/fesm2022/radix-ng-primitives-time-field.mjs +5 -3
  62. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  63. package/fesm2022/radix-ng-primitives-toast.mjs +15 -36
  64. package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
  65. package/fesm2022/radix-ng-primitives-toggle-group.mjs +5 -3
  66. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  67. package/fesm2022/radix-ng-primitives-toolbar.mjs +5 -3
  68. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  69. package/fesm2022/radix-ng-primitives-tooltip.mjs +105 -145
  70. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  71. package/package.json +14 -1
  72. package/types/radix-ng-primitives-accordion.d.ts +4 -3
  73. package/types/radix-ng-primitives-alert-dialog.d.ts +17 -11
  74. package/types/radix-ng-primitives-autocomplete.d.ts +661 -0
  75. package/types/radix-ng-primitives-calendar.d.ts +5 -3
  76. package/types/radix-ng-primitives-combobox.d.ts +727 -293
  77. package/types/radix-ng-primitives-config.d.ts +1 -1
  78. package/types/radix-ng-primitives-context-menu.d.ts +15 -5
  79. package/types/radix-ng-primitives-core.d.ts +762 -14
  80. package/types/radix-ng-primitives-date-field.d.ts +3 -2
  81. package/types/radix-ng-primitives-dialog.d.ts +107 -55
  82. package/types/radix-ng-primitives-direction-provider.d.ts +41 -0
  83. package/types/radix-ng-primitives-dismissable-layer.d.ts +147 -99
  84. package/types/radix-ng-primitives-drawer.d.ts +49 -22
  85. package/types/radix-ng-primitives-field.d.ts +1 -0
  86. package/types/radix-ng-primitives-floating-focus-manager.d.ts +175 -0
  87. package/types/radix-ng-primitives-focus-scope.d.ts +132 -1
  88. package/types/radix-ng-primitives-menu.d.ts +204 -112
  89. package/types/radix-ng-primitives-navigation-menu.d.ts +61 -101
  90. package/types/radix-ng-primitives-popover.d.ts +82 -115
  91. package/types/radix-ng-primitives-popper.d.ts +46 -10
  92. package/types/radix-ng-primitives-portal.d.ts +53 -8
  93. package/types/radix-ng-primitives-presence.d.ts +98 -17
  94. package/types/radix-ng-primitives-preview-card.d.ts +63 -95
  95. package/types/radix-ng-primitives-roving-focus.d.ts +7 -6
  96. package/types/radix-ng-primitives-scroll-area.d.ts +2 -2
  97. package/types/radix-ng-primitives-select.d.ts +192 -158
  98. package/types/radix-ng-primitives-slider.d.ts +5 -4
  99. package/types/radix-ng-primitives-stepper.d.ts +4 -3
  100. package/types/radix-ng-primitives-time-field.d.ts +3 -2
  101. package/types/radix-ng-primitives-toast.d.ts +7 -7
  102. package/types/radix-ng-primitives-toggle-group.d.ts +5 -4
  103. package/types/radix-ng-primitives-toolbar.d.ts +3 -2
  104. package/types/radix-ng-primitives-tooltip.d.ts +48 -84
@@ -1,17 +1,17 @@
1
1
  import * as i0 from '@angular/core';
2
- import { booleanAttribute, inject, DestroyRef, signal, model, input, output, computed, effect, untracked, Directive, ElementRef, numberAttribute, afterNextRender, NgModule } from '@angular/core';
2
+ import { booleanAttribute, inject, DestroyRef, ElementRef, signal, model, input, output, computed, effect, untracked, Directive, isDevMode, numberAttribute, afterNextRender, NgModule } from '@angular/core';
3
3
  import * as i1 from '@radix-ng/primitives/popper';
4
- import { RdxPopper, RdxPopperContentWrapper, RdxPopperArrow, RdxPopperContent, provideRdxPopperContentConfig, RdxPopperAnchor } from '@radix-ng/primitives/popper';
5
- import { createContext, useTransitionStatus, injectId, useScrollLock, useGraceArea } from '@radix-ng/primitives/core';
4
+ import { RdxPopper, RdxPopperContentWrapper, RdxPopperArrow, RdxPopperContent, legacyPopperVars, provideRdxPopperContentWrapper, provideRdxPopperContentConfig, RdxPopperAnchor } from '@radix-ng/primitives/popper';
5
+ import * as i2 from '@radix-ng/primitives/core';
6
+ import { createContext, createFloatingRootContext, useTransitionStatus, injectId, createCancelableChangeEventDetails, provideFloatingTree, provideFloatingRootContext, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_REGISTRATION, useAnchoredScrollLock, RdxFloatingNodeRegistration, rdxDevError, useGraceArea } from '@radix-ng/primitives/core';
6
7
  import { outputFromObservable, outputToObservable } from '@angular/core/rxjs-interop';
7
- import * as i2 from '@radix-ng/primitives/dismissable-layer';
8
- import { RdxDismissableLayer, provideRdxDismissableLayerConfig } from '@radix-ng/primitives/dismissable-layer';
9
- import * as i3 from '@radix-ng/primitives/focus-scope';
10
- import { RdxFocusScope, provideRdxFocusScopeConfig } from '@radix-ng/primitives/focus-scope';
8
+ import { RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
9
+ import * as i3 from '@radix-ng/primitives/floating-focus-manager';
10
+ import { RdxFloatingFocusManager, provideFloatingFocusManagerConfig } from '@radix-ng/primitives/floating-focus-manager';
11
+ import { RdxFocusScope } from '@radix-ng/primitives/focus-scope';
11
12
  import * as i1$1 from '@radix-ng/primitives/portal';
12
- import { RdxPortal } from '@radix-ng/primitives/portal';
13
- import * as i1$2 from '@radix-ng/primitives/presence';
14
- import { provideRdxPresenceContext, RdxPresenceDirective } from '@radix-ng/primitives/presence';
13
+ import { RdxPortalPresence } from '@radix-ng/primitives/portal';
14
+ import { provideRdxPresenceContext } from '@radix-ng/primitives/presence';
15
15
 
16
16
  const transformModal = (value) => value === 'trap-focus' ? value : booleanAttribute(value);
17
17
  const context = () => contextFor(inject(RdxPopoverRoot));
@@ -23,6 +23,11 @@ class RdxPopoverRoot {
23
23
  constructor() {
24
24
  this.popper = inject(RdxPopper);
25
25
  this.destroyRef = inject(DestroyRef);
26
+ /** Shared per-popup floating context (ADR 0015 §1): `open`, trigger registry, reference / floating els. */
27
+ this.floatingContext = createFloatingRootContext({
28
+ ownerDocument: inject(ElementRef).nativeElement.ownerDocument,
29
+ open: () => this.open()
30
+ });
26
31
  this.hasAppliedDefaultOpen = false;
27
32
  this.hasAppliedDefaultTriggerId = false;
28
33
  this.hoverDelay = 300;
@@ -66,45 +71,60 @@ class RdxPopoverRoot {
66
71
  this.triggers = signal([], ...(ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []));
67
72
  this.payload = signal(undefined, ...(ngDevMode ? [{ debugName: "payload" }] : /* istanbul ignore next */ []));
68
73
  this.isPointerDownOnTrigger = signal(false, ...(ngDevMode ? [{ debugName: "isPointerDownOnTrigger" }] : /* istanbul ignore next */ []));
74
+ /** Whether the current open was initiated by touch (ADR 0016 §3 — gates the anchored scroll lock). */
75
+ this.openedByTouch = signal(false, ...(ngDevMode ? [{ debugName: "openedByTouch" }] : /* istanbul ignore next */ []));
69
76
  this.popupCloseCount = signal(0, ...(ngDevMode ? [{ debugName: "popupCloseCount" }] : /* istanbul ignore next */ []));
77
+ this.preventUnmountOnClose = signal(false, ...(ngDevMode ? [{ debugName: "preventUnmountOnClose" }] : /* istanbul ignore next */ []));
70
78
  this.onOpenChange = output();
71
79
  this.onOpenChangeComplete = output();
72
80
  this.registeredTriggers = new Map();
73
81
  this.viewportTriggerChange = new Set();
74
- this.state = computed(() => (this.open() ? 'open' : 'closed'), ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
82
+ this.state = computed(() => (this.open() ? 'open' : 'closed'), { debugName: 'RdxPopoverRoot.state' });
83
+ this.present = computed(() => this.open() || this.preventUnmountOnClose(), {
84
+ debugName: 'RdxPopoverRoot.present'
85
+ });
75
86
  let previousOpen = this.open();
87
+ // Keep the floating context's reference element in sync with the active trigger.
88
+ effect(() => this.floatingContext.setReferenceElement(this.trigger() ?? null));
89
+ effect(() => {
90
+ if (this.open() && this.preventUnmountOnClose()) {
91
+ this.preventUnmountOnClose.set(false);
92
+ }
93
+ }, { debugName: 'RdxPopoverRoot.clearPreventUnmountOnOpen' });
76
94
  effect(() => {
77
95
  const defaultOpen = this.defaultOpen();
78
96
  if (!this.hasAppliedDefaultOpen && defaultOpen) {
79
97
  this.hasAppliedDefaultOpen = true;
80
98
  this.open.set(defaultOpen);
81
99
  }
82
- });
100
+ }, { debugName: 'RdxPopoverRoot.applyDefaultOpen' });
83
101
  effect(() => {
84
102
  const defaultTriggerId = this.defaultTriggerId();
85
103
  if (!this.hasAppliedDefaultTriggerId && defaultTriggerId !== null) {
86
104
  this.hasAppliedDefaultTriggerId = true;
87
105
  this.triggerId.set(defaultTriggerId);
88
106
  }
89
- });
107
+ }, { debugName: 'RdxPopoverRoot.applyDefaultTriggerId' });
90
108
  effect(() => {
91
109
  const triggerId = this.triggerId();
92
110
  untracked(() => this.syncTriggerId(triggerId));
93
- });
111
+ }, { debugName: 'RdxPopoverRoot.syncTriggerId' });
94
112
  effect(() => {
95
113
  const open = this.open();
96
114
  if (open !== previousOpen) {
97
115
  previousOpen = open;
98
116
  untracked(() => this.transition.start(open));
99
117
  }
100
- });
118
+ }, { debugName: 'RdxPopoverRoot.startTransition' });
101
119
  effect((onCleanup) => {
102
120
  const handle = this.handle();
103
121
  if (handle) {
104
122
  onCleanup(untracked(() => handle.registerRoot(contextFor(this))));
105
123
  }
124
+ }, { debugName: 'RdxPopoverRoot.registerHandle' });
125
+ effect(() => this.popper.anchorOverride.set(this.trigger()), {
126
+ debugName: 'RdxPopoverRoot.syncAnchorOverride'
106
127
  });
107
- effect(() => this.popper.anchorOverride.set(this.trigger()));
108
128
  this.destroyRef.onDestroy(() => {
109
129
  this.clearHoverTimers();
110
130
  if (this.instantFrame !== undefined) {
@@ -114,10 +134,25 @@ class RdxPopoverRoot {
114
134
  }
115
135
  show(trigger = this.trigger(), payload, triggerId, reason = 'none', event = new Event('popover.open-change'), fromHover = false) {
116
136
  this.clearHoverTimers();
117
- this.isHoverActive.set(fromHover);
118
- this.openChangeReason.set(reason);
119
137
  const previousTrigger = this.trigger();
120
138
  const changedTriggerWhileOpen = this.open() && previousTrigger !== trigger;
139
+ const changed = !this.open() || previousTrigger !== trigger;
140
+ if (!changed) {
141
+ this.isHoverActive.set(fromHover);
142
+ this.openChangeReason.set(reason);
143
+ if (triggerId !== undefined) {
144
+ this.triggerId.set(triggerId);
145
+ }
146
+ this.payload.set(payload);
147
+ return;
148
+ }
149
+ const change = this.createOpenChangeEvent(true, reason, event, trigger, triggerId ?? this.triggerId());
150
+ this.onOpenChange.emit(change.payload);
151
+ if (change.eventDetails.isCanceled()) {
152
+ return;
153
+ }
154
+ this.isHoverActive.set(fromHover);
155
+ this.openChangeReason.set(reason);
121
156
  this.instant.set(changedTriggerWhileOpen || reason === 'trigger-focus');
122
157
  if (changedTriggerWhileOpen) {
123
158
  this.scheduleInstantReset();
@@ -132,22 +167,27 @@ class RdxPopoverRoot {
132
167
  this.triggerId.set(triggerId);
133
168
  }
134
169
  this.payload.set(payload);
135
- const changed = !this.open() || previousTrigger !== trigger;
170
+ this.preventUnmountOnClose.set(false);
136
171
  this.open.set(true);
137
- if (changed) {
138
- this.emitOpenChange(true, reason, event);
139
- }
172
+ this.floatingContext.events.emit('openchange', { open: true, reason, event: change.eventDetails.event });
140
173
  }
141
174
  close(reason = 'none', event = new Event('popover.open-change')) {
142
175
  this.clearHoverTimers();
143
- this.isHoverActive.set(false);
144
176
  if (!this.open()) {
145
177
  return;
146
178
  }
179
+ const change = this.createOpenChangeEvent(false, reason, event, this.trigger(), this.triggerId());
180
+ this.onOpenChange.emit(change.payload);
181
+ if (change.eventDetails.isCanceled()) {
182
+ return;
183
+ }
184
+ this.isHoverActive.set(false);
185
+ this.openedByTouch.set(false);
147
186
  this.instant.set(reason !== 'none' && reason !== 'trigger-hover');
148
187
  this.openChangeReason.set(reason);
188
+ this.preventUnmountOnClose.set(change.shouldPreventUnmountOnClose());
149
189
  this.open.set(false);
150
- this.emitOpenChange(false, reason, event);
190
+ this.floatingContext.events.emit('openchange', { open: false, reason, event: change.eventDetails.event });
151
191
  }
152
192
  toggle(triggerId, trigger, payload, event) {
153
193
  this.clearHoverTimers();
@@ -187,6 +227,8 @@ class RdxPopoverRoot {
187
227
  registerTrigger(id, trigger, payload) {
188
228
  this.registeredTriggers.set(id, { element: trigger, payload });
189
229
  this.triggers.update((triggers) => (triggers.includes(trigger) ? triggers : [...triggers, trigger]));
230
+ // Bridge into the floating context's trigger registry (new dismissal/focus inside-element checks).
231
+ this.floatingContext.triggers.add(trigger);
190
232
  if (this.triggerId() === id) {
191
233
  this.trigger.set(trigger);
192
234
  this.payload.set(payload());
@@ -200,6 +242,7 @@ class RdxPopoverRoot {
200
242
  this.registeredTriggers.delete(id);
201
243
  }
202
244
  this.triggers.update((triggers) => triggers.filter((candidate) => candidate !== trigger));
245
+ this.floatingContext.triggers.delete(trigger);
203
246
  if (this.destroyRef.destroyed) {
204
247
  return;
205
248
  }
@@ -245,14 +288,20 @@ class RdxPopoverRoot {
245
288
  this.trigger.set(trigger.element);
246
289
  this.payload.set(trigger.payload());
247
290
  }
248
- emitOpenChange(open, reason, event) {
249
- this.onOpenChange.emit({
250
- open,
251
- triggerId: this.triggerId(),
252
- trigger: this.trigger(),
253
- reason,
254
- event
255
- });
291
+ createOpenChangeEvent(open, reason, event, trigger, triggerId) {
292
+ const change = createCancelableChangeEventDetails(reason, event, trigger);
293
+ return {
294
+ eventDetails: change.eventDetails,
295
+ shouldPreventUnmountOnClose: change.shouldPreventUnmountOnClose,
296
+ payload: {
297
+ open,
298
+ triggerId,
299
+ trigger: change.eventDetails.trigger,
300
+ reason: change.eventDetails.reason,
301
+ event: change.eventDetails.event,
302
+ eventDetails: change.eventDetails
303
+ }
304
+ };
256
305
  }
257
306
  clearHoverTimers() {
258
307
  this.clearOpenTimer();
@@ -282,14 +331,26 @@ class RdxPopoverRoot {
282
331
  });
283
332
  }
284
333
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
285
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPopoverRoot, isStandalone: true, selector: "[rdxPopoverRoot]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, triggerId: { classPropertyName: "triggerId", publicName: "triggerId", isSignal: true, isRequired: false, transformFunction: null }, defaultTriggerId: { classPropertyName: "defaultTriggerId", publicName: "defaultTriggerId", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", triggerId: "triggerIdChange", onOpenChange: "onOpenChange", onOpenChangeComplete: "onOpenChangeComplete" }, providers: [provideRdxPopoverRootContext(context)], exportAs: ["rdxPopoverRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
334
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPopoverRoot, isStandalone: true, selector: "[rdxPopoverRoot]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, triggerId: { classPropertyName: "triggerId", publicName: "triggerId", isSignal: true, isRequired: false, transformFunction: null }, defaultTriggerId: { classPropertyName: "defaultTriggerId", publicName: "defaultTriggerId", isSignal: true, isRequired: false, transformFunction: null }, modal: { classPropertyName: "modal", publicName: "modal", isSignal: true, isRequired: false, transformFunction: null }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", triggerId: "triggerIdChange", onOpenChange: "onOpenChange", onOpenChangeComplete: "onOpenChangeComplete" }, providers: [
335
+ provideRdxPopoverRootContext(context),
336
+ // New floating foundation (ADR 0015/0017 migration). Inherit-or-create tree (nested sharing);
337
+ // the per-popup root context bridges open / triggers / reference.
338
+ provideFloatingTree(),
339
+ provideFloatingRootContext(() => inject(RdxPopoverRoot).floatingContext)
340
+ ], exportAs: ["rdxPopoverRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
286
341
  }
287
342
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverRoot, decorators: [{
288
343
  type: Directive,
289
344
  args: [{
290
345
  selector: '[rdxPopoverRoot]',
291
346
  exportAs: 'rdxPopoverRoot',
292
- providers: [provideRdxPopoverRootContext(context)],
347
+ providers: [
348
+ provideRdxPopoverRootContext(context),
349
+ // New floating foundation (ADR 0015/0017 migration). Inherit-or-create tree (nested sharing);
350
+ // the per-popup root context bridges open / triggers / reference.
351
+ provideFloatingTree(),
352
+ provideFloatingRootContext(() => inject(RdxPopoverRoot).floatingContext)
353
+ ],
293
354
  hostDirectives: [RdxPopper]
294
355
  }]
295
356
  }], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], defaultOpen: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultOpen", required: false }] }], triggerId: [{ type: i0.Input, args: [{ isSignal: true, alias: "triggerId", required: false }] }, { type: i0.Output, args: ["triggerIdChange"] }], defaultTriggerId: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultTriggerId", required: false }] }], modal: [{ type: i0.Input, args: [{ isSignal: true, alias: "modal", required: false }] }], handle: [{ type: i0.Input, args: [{ isSignal: true, alias: "handle", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onOpenChangeComplete: [{ type: i0.Output, args: ["onOpenChangeComplete"] }] } });
@@ -298,6 +359,7 @@ function contextFor(root) {
298
359
  contentId: root.contentId,
299
360
  descriptionId: root.descriptionId.asReadonly(),
300
361
  isOpen: root.open,
362
+ present: root.present,
301
363
  modal: root.modal,
302
364
  titleId: root.titleId.asReadonly(),
303
365
  trigger: root.trigger.asReadonly(),
@@ -308,6 +370,7 @@ function contextFor(root) {
308
370
  instant: root.instant.asReadonly(),
309
371
  openChangeReason: root.openChangeReason.asReadonly(),
310
372
  isPointerDownOnTrigger: root.isPointerDownOnTrigger.asReadonly(),
373
+ openedByTouch: root.openedByTouch.asReadonly(),
311
374
  close: (reason, event) => root.close(reason, event),
312
375
  cancelHoverClose: () => root.cancelHoverClose(),
313
376
  cancelHoverOpen: () => root.cancelHoverOpen(),
@@ -318,6 +381,7 @@ function contextFor(root) {
318
381
  setDescriptionId: (id) => root.descriptionId.set(id),
319
382
  setTitleId: (id) => root.titleId.set(id),
320
383
  setPointerDownOnTrigger: (pointerDown) => root.isPointerDownOnTrigger.set(pointerDown),
384
+ setOpenedByTouch: (value) => root.openedByTouch.set(value),
321
385
  setHoverDelays: (delay, closeDelay) => root.setHoverDelays(delay, closeDelay),
322
386
  registerPopupClose: () => {
323
387
  root.popupCloseCount.update((count) => count + 1);
@@ -365,6 +429,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
365
429
  class RdxPopoverBackdrop {
366
430
  constructor() {
367
431
  this.rootContext = injectRdxPopoverRootContext();
432
+ // Register the backdrop as owned DOM footprint for primitive-specific checks. The focus manager's
433
+ // marker keep-set stays narrow and does not keep sibling backdrop roots.
434
+ const floatingContext = inject(RDX_FLOATING_ROOT_CONTEXT, { optional: true });
435
+ if (floatingContext) {
436
+ const host = inject(ElementRef).nativeElement;
437
+ floatingContext.addFloatingElement(host);
438
+ inject(DestroyRef).onDestroy(() => floatingContext.removeFloatingElement(host));
439
+ }
368
440
  }
369
441
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverBackdrop, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
370
442
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPopoverBackdrop, isStandalone: true, selector: "[rdxPopoverBackdrop]", host: { properties: { "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-ending-style": "rootContext.transitionStatus() === \"ending\" ? \"\" : undefined", "attr.data-instant": "rootContext.instant() ? \"\" : undefined", "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-starting-style": "rootContext.transitionStatus() === \"starting\" ? \"\" : undefined", "attr.data-state": "rootContext.isOpen() ? \"open\" : \"closed\"" } }, ngImport: i0 }); }
@@ -382,109 +454,126 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
382
454
  '[attr.data-state]': 'rootContext.isOpen() ? "open" : "closed"'
383
455
  }
384
456
  }]
385
- }] });
457
+ }], ctorParameters: () => [] });
386
458
 
387
459
  /**
388
460
  * A container for the popover contents.
461
+ *
462
+ * **ADR 0015/0017 Phase-4 migration** onto the new floating dismissal + focus engine (same pattern as
463
+ * Dialog; browser-verified via `popover.behavior` Playwright). Popover-specific:
464
+ * - **Hover-open disables the manager** (`enabled = isOpen && !isHoverActive`) — Base UI parity
465
+ * (`disabled={!mounted || openReason === triggerHover}`); a hover-opened popover does not trap / mark.
466
+ * (The legacy only suppressed auto-focus while still trapping — that Radix divergence is dropped.)
467
+ * - Trap = `'trap-focus' || (modal === true && hasPopupClose())`; scroll lock + real outside `inert`
468
+ * isolation key off the full modal (`modal === true`).
469
+ * - No `disablePointerDismissal` — outside-press + focus-out always close.
470
+ *
471
+ * Note: a positioned popover does **not** auto-focus into the popup on open (pre-existing — the legacy
472
+ * behaved the same; verified). The trap holds focus once it is inside. Auto-focus-on-open + redirecting a
473
+ * Tab from the trigger into the popup needs the deferred portal-focus bridge / guards (ADR 0017 §6a).
389
474
  */
390
475
  class RdxPopoverPopup {
391
476
  constructor() {
392
477
  this.rootContext = injectRdxPopoverRootContext();
393
- this.dismissableLayer = inject(RdxDismissableLayer);
478
+ this.host = inject(ElementRef).nativeElement;
479
+ this.floatingContext = inject(RDX_FLOATING_ROOT_CONTEXT);
480
+ this.registration = inject(RDX_FLOATING_REGISTRATION, { optional: true });
481
+ this.focusManager = inject(RdxFloatingFocusManager);
394
482
  this.focusScope = inject(RdxFocusScope);
395
483
  this.wrapper = inject(RdxPopperContentWrapper, { optional: true });
396
484
  this.align = computed(() => this.wrapper?.placedAlign(), ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
397
485
  this.side = computed(() => this.wrapper?.placedSide(), ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
398
- this.dismissDetails = {
399
- reason: 'none',
400
- event: new Event('popover.dismiss')
401
- };
402
- /**
403
- * Event handler called when the escape key is down. Can be prevented.
404
- */
405
- this.escapeKeyDown = outputFromObservable(outputToObservable(this.dismissableLayer.escapeKeyDown));
406
- /**
407
- * Event handler called when a pointerdown event happens outside of the popup. Can be prevented.
408
- */
409
- this.pointerDownOutside = outputFromObservable(outputToObservable(this.dismissableLayer.pointerDownOutside));
410
- /**
411
- * Event handler called when focus moves outside of the popup. Can be prevented.
412
- */
413
- this.focusOutside = outputFromObservable(outputToObservable(this.dismissableLayer.focusOutside));
414
- /**
415
- * Event handler called when an interaction happens outside of the popup. Can be prevented.
416
- */
417
- this.interactOutside = outputFromObservable(outputToObservable(this.dismissableLayer.interactOutside));
418
- /**
419
- * Event handler called before focus moves into the popup. Can be prevented.
420
- */
486
+ /** Event handler called when the escape key is down. Can be prevented. */
487
+ this.escapeKeyDown = output();
488
+ /** Event handler called when a pointerdown event happens outside of the popup. Can be prevented. */
489
+ this.pointerDownOutside = output();
490
+ /** Event handler called when focus moves outside of the popup. Can be prevented. */
491
+ this.focusOutside = output();
492
+ /** Event handler called when an interaction (pointer / focus) happens outside of the popup. */
493
+ this.interactOutside = output();
494
+ /** Event handler called before focus moves into the popup. Can be prevented. */
421
495
  this.openAutoFocus = outputFromObservable(outputToObservable(this.focusScope.mountAutoFocus));
422
- /**
423
- * Event handler called before focus returns after the popup is removed. Can be prevented.
424
- */
496
+ /** Event handler called before focus returns after the popup is removed. Can be prevented. */
425
497
  this.closeAutoFocus = outputFromObservable(outputToObservable(this.focusScope.unmountAutoFocus));
426
- useScrollLock(computed(() => this.rootContext.modal() === true));
427
- const unregisterTransitionElement = this.rootContext.registerTransitionElement(inject(ElementRef).nativeElement);
498
+ this.floatingContext.setFloatingElement(this.host);
499
+ // Background pointer/AT isolation for a full modal is the focus manager's `inert` pass (finding
500
+ // #4), not a global body lock; only the page scroll lock stays here. Activation policy (ADR 0016
501
+ // §2): lock only while a `modal === true` popover is OPEN and was **not** hover-opened, gated on
502
+ // `open` (not mounted) so it releases at close-start. For a **touch** open the anchored helper only
503
+ // locks when the popup is effectively viewport-width (a small popover stays swipe-to-dismissable on
504
+ // mobile, §3).
505
+ useAnchoredScrollLock(computed(() => this.rootContext.isOpen() && this.rootContext.modal() === true && !this.rootContext.isHoverActive()), {
506
+ touchOpen: () => this.rootContext.openedByTouch(),
507
+ element: () => this.host
508
+ });
509
+ const unregisterTransitionElement = this.rootContext.registerTransitionElement(this.host);
428
510
  inject(DestroyRef).onDestroy(unregisterTransitionElement);
429
- this.dismissableLayer.pointerDownOutside.subscribe((event) => {
430
- this.dismissDetails = { reason: 'outside-press', event };
431
- if (this.rootContext.triggers().some((trigger) => trigger.contains(event.target))) {
511
+ // A hover-opened popover must not steal focus — suppress the composed focus scope's auto-focus.
512
+ this.focusScope.mountAutoFocus.subscribe((event) => {
513
+ if (this.rootContext.isHoverActive()) {
432
514
  event.preventDefault();
433
515
  }
434
516
  });
435
- this.dismissableLayer.focusOutside.subscribe((event) => {
436
- this.dismissDetails = { reason: 'focus-out', event };
437
- if (this.rootContext.isPointerDownOnTrigger()) {
438
- event.preventDefault();
517
+ // Dismissal: Escape + outside-press always close (no pointer-dismissal opt-out). Focus-out is
518
+ // owned by the focus manager (below), so the capability's own focus-out is disabled.
519
+ new RdxDismiss(this.floatingContext, () => this.registration?.node() ?? null, {
520
+ escapeKey: () => true,
521
+ outsidePress: () => true,
522
+ focusOutside: () => false,
523
+ onEscapeKeyDown: (event) => this.escapeKeyDown.emit(event),
524
+ onPointerDownOutside: (event) => {
525
+ this.pointerDownOutside.emit(event);
526
+ this.interactOutside.emit(event);
527
+ },
528
+ onDismiss: (reason, event) => {
529
+ this.rootContext.close(reason === 'escape-key' ? 'escape-key' : 'outside-press', event);
439
530
  }
440
531
  });
441
- this.dismissableLayer.escapeKeyDown.subscribe((event) => {
442
- this.dismissDetails = { reason: 'escape-key', event };
443
- });
444
- this.focusScope.mountAutoFocus.subscribe((event) => {
445
- if (this.rootContext.isHoverActive()) {
446
- event.preventDefault();
532
+ // Focus-out close (ADR 0017 §3) — re-expose as `focusOutside` (preventable) and close unless vetoed.
533
+ this.focusManager.focusOut.subscribe((event) => {
534
+ this.focusOutside.emit(event);
535
+ this.interactOutside.emit(event);
536
+ if (!event.defaultPrevented) {
537
+ this.rootContext.close('focus-out', event);
447
538
  }
448
539
  });
449
- this.dismissableLayer.dismiss.subscribe(() => {
450
- this.rootContext.close(this.dismissDetails.reason, this.dismissDetails.event);
451
- this.dismissDetails = { reason: 'none', event: new Event('popover.dismiss') };
452
- });
453
540
  }
454
541
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPopup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
455
542
  static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPopoverPopup, isStandalone: true, selector: "[rdxPopoverPopup]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside", focusOutside: "focusOutside", interactOutside: "interactOutside", openAutoFocus: "openAutoFocus", closeAutoFocus: "closeAutoFocus" }, host: { attributes: { "role": "dialog" }, listeners: { "pointerenter": "rootContext.cancelHoverClose()" }, properties: { "attr.aria-describedby": "rootContext.descriptionId()", "attr.aria-labelledby": "rootContext.titleId()", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-ending-style": "rootContext.transitionStatus() === \"ending\" ? \"\" : undefined", "attr.data-instant": "rootContext.instant() ? \"\" : undefined", "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-starting-style": "rootContext.transitionStatus() === \"starting\" ? \"\" : undefined", "attr.data-state": "rootContext.isOpen() ? \"open\" : \"closed\"", "attr.data-align": "align()", "attr.data-side": "side()", "id": "rootContext.contentId" } }, providers: [
456
- provideRdxDismissableLayerConfig(() => {
457
- const rootContext = injectRdxPopoverRootContext();
458
- return {
459
- disableOutsidePointerEvents: computed(() => rootContext.modal() === true)
460
- };
461
- }),
462
- provideRdxFocusScopeConfig(() => {
543
+ provideFloatingFocusManagerConfig(() => {
463
544
  const rootContext = injectRdxPopoverRootContext();
464
545
  return {
465
- trapped: computed(() => rootContext.modal() === 'trap-focus' ||
466
- (rootContext.modal() === true && rootContext.hasPopupClose()))
546
+ modal: () => rootContext.modal() === 'trap-focus' ||
547
+ (rootContext.modal() === true && rootContext.hasPopupClose()),
548
+ // Full modal blocks outside pointer interaction; `trap-focus` only traps focus.
549
+ inert: () => rootContext.modal() === true && rootContext.hasPopupClose(),
550
+ // Active for the whole MOUNTED lifetime (Base UI `disabled={!mounted}`, not `open`) for
551
+ // trap/return-focus — including an explicit `preventUnmountOnClose()` cycle after the
552
+ // exit transition. Marker + isolation are additionally gated on `open` inside the
553
+ // manager. Still suppressed while hover-opened.
554
+ enabled: () => rootContext.present() && !rootContext.isHoverActive()
467
555
  };
468
556
  })
469
- ], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxDismissableLayer }, { directive: i3.RdxFocusScope }], ngImport: i0 }); }
557
+ ], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxFloatingNodeRegistration }, { directive: i3.RdxFloatingFocusManager }], ngImport: i0 }); }
470
558
  }
471
559
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPopup, decorators: [{
472
560
  type: Directive,
473
561
  args: [{
474
562
  selector: '[rdxPopoverPopup]',
475
- hostDirectives: [RdxPopperContent, RdxDismissableLayer, RdxFocusScope],
563
+ hostDirectives: [RdxPopperContent, RdxFloatingNodeRegistration, RdxFloatingFocusManager],
476
564
  providers: [
477
- provideRdxDismissableLayerConfig(() => {
478
- const rootContext = injectRdxPopoverRootContext();
479
- return {
480
- disableOutsidePointerEvents: computed(() => rootContext.modal() === true)
481
- };
482
- }),
483
- provideRdxFocusScopeConfig(() => {
565
+ provideFloatingFocusManagerConfig(() => {
484
566
  const rootContext = injectRdxPopoverRootContext();
485
567
  return {
486
- trapped: computed(() => rootContext.modal() === 'trap-focus' ||
487
- (rootContext.modal() === true && rootContext.hasPopupClose()))
568
+ modal: () => rootContext.modal() === 'trap-focus' ||
569
+ (rootContext.modal() === true && rootContext.hasPopupClose()),
570
+ // Full modal blocks outside pointer interaction; `trap-focus` only traps focus.
571
+ inert: () => rootContext.modal() === true && rootContext.hasPopupClose(),
572
+ // Active for the whole MOUNTED lifetime (Base UI `disabled={!mounted}`, not `open`) for
573
+ // trap/return-focus — including an explicit `preventUnmountOnClose()` cycle after the
574
+ // exit transition. Marker + isolation are additionally gated on `open` inside the
575
+ // manager. Still suppressed while hover-opened.
576
+ enabled: () => rootContext.present() && !rootContext.isHoverActive()
488
577
  };
489
578
  })
490
579
  ],
@@ -555,191 +644,96 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
555
644
  }], ctorParameters: () => [] });
556
645
 
557
646
  /**
558
- * Moves the popover to a different part of the DOM.
647
+ * Structural directive that teleports the popover content into a container (default `document.body`)
648
+ * while the popover is open, and keeps it mounted until any CSS exit `@keyframes` finishes.
649
+ *
650
+ * Apply it with the `*` microsyntax on the positioner — `<div *rdxPopoverPortal rdxPopoverPositioner>`
651
+ * — or as an explicit `<ng-template rdxPopoverPortal>`. For a custom container use the explicit form
652
+ * with `[container]`.
559
653
  */
560
654
  class RdxPopoverPortal {
561
- constructor() {
562
- this.rootContext = injectRdxPopoverRootContext();
563
- /**
564
- * Optional container to portal the content into. Defaults to `document.body`.
565
- */
566
- this.container = input(...(ngDevMode ? [undefined, { debugName: "container" }] : /* istanbul ignore next */ []));
567
- }
568
655
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
569
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPopoverPortal, isStandalone: true, selector: "[rdxPopoverPortal]", inputs: { container: { classPropertyName: "container", publicName: "container", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-state": "rootContext.isOpen() ? \"open\" : \"closed\"" } }, hostDirectives: [{ directive: i1$1.RdxPortal, inputs: ["container", "container"] }], ngImport: i0 }); }
656
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPopoverPortal, isStandalone: true, selector: "ng-template[rdxPopoverPortal]", providers: [provideRdxPresenceContext(() => ({ present: injectRdxPopoverRootContext().present }))], exportAs: ["rdxPopoverPortal"], hostDirectives: [{ directive: i1$1.RdxPortalPresence, inputs: ["container", "container"] }], ngImport: i0 }); }
570
657
  }
571
658
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPortal, decorators: [{
572
659
  type: Directive,
573
660
  args: [{
574
- selector: '[rdxPopoverPortal]',
575
- hostDirectives: [
576
- {
577
- directive: RdxPortal,
578
- inputs: ['container']
579
- }
580
- ],
581
- host: {
582
- '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
583
- '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
584
- '[attr.data-state]': 'rootContext.isOpen() ? "open" : "closed"'
585
- }
661
+ selector: 'ng-template[rdxPopoverPortal]',
662
+ exportAs: 'rdxPopoverPortal',
663
+ hostDirectives: [{ directive: RdxPortalPresence, inputs: ['container'] }],
664
+ providers: [provideRdxPresenceContext(() => ({ present: injectRdxPopoverRootContext().present }))]
586
665
  }]
587
- }], propDecorators: { container: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }] } });
588
-
666
+ }] });
589
667
  /**
590
- * Mounts the portal while the popover is open and waits for CSS exit keyframes before unmounting.
668
+ * Dev-mode guard: `rdxPopoverPortal` used to be an attribute directive on a `<div>`. It is now
669
+ * structural, so the old `<div rdxPopoverPortal>` markup would silently stop portaling — fail loudly
670
+ * instead.
591
671
  */
592
- class RdxPopoverPortalPresence {
593
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPortalPresence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
594
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPopoverPortalPresence, isStandalone: true, selector: "ng-template[rdxPopoverPortalPresence]", providers: [
595
- provideRdxPresenceContext(() => {
596
- const context = injectRdxPopoverRootContext();
597
- return { present: context.isOpen };
598
- })
599
- ], hostDirectives: [{ directive: i1$2.RdxPresenceDirective }], ngImport: i0 }); }
672
+ class RdxPopoverPortalMisuseGuard {
673
+ constructor() {
674
+ if (isDevMode()) {
675
+ rdxDevError('popover/portal-on-element', '`rdxPopoverPortal` is now a structural directive. ' +
676
+ 'Use `*rdxPopoverPortal` on the positioner element or `<ng-template rdxPopoverPortal>`. ' +
677
+ 'rdxPopoverPortalPresence has been removed.', 'components/popover');
678
+ }
679
+ }
680
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPortalMisuseGuard, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
681
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPopoverPortalMisuseGuard, isStandalone: true, selector: "[rdxPopoverPortal]:not(ng-template)", ngImport: i0 }); }
600
682
  }
601
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPortalPresence, decorators: [{
683
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPortalMisuseGuard, decorators: [{
602
684
  type: Directive,
603
685
  args: [{
604
- selector: 'ng-template[rdxPopoverPortalPresence]',
605
- hostDirectives: [RdxPresenceDirective],
606
- providers: [
607
- provideRdxPresenceContext(() => {
608
- const context = injectRdxPopoverRootContext();
609
- return { present: context.isOpen };
610
- })
611
- ]
686
+ selector: '[rdxPopoverPortal]:not(ng-template)'
612
687
  }]
613
- }] });
688
+ }], ctorParameters: () => [] });
614
689
 
615
690
  /**
616
691
  * Positions the popover against its trigger.
692
+ *
693
+ * A "thin" positioner (ADR 0012): it inherits the popper positioning surface (inputs, `placed`
694
+ * output, unified vars + placement attrs) from {@link RdxPopperContentWrapper} and adds popover's own
695
+ * concerns — Base UI-aligned defaults via the config provider, the open/closed/instant state
696
+ * attributes, the deprecated `--radix-popover-*` aliases, and the grace-area hover bridge.
617
697
  */
618
- class RdxPopoverPositioner {
698
+ class RdxPopoverPositioner extends RdxPopperContentWrapper {
619
699
  constructor() {
700
+ super();
620
701
  this.rootContext = injectRdxPopoverRootContext();
621
- this.wrapper = inject(RdxPopperContentWrapper);
622
- this.elementRef = inject(ElementRef);
702
+ this.legacyVars = legacyPopperVars('popover');
703
+ this.containerRef = inject(ElementRef);
623
704
  this.triggerEl = signal(null, ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
624
- this.containerEl = signal(this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "containerEl" }] : /* istanbul ignore next */ []));
705
+ this.containerEl = signal(this.containerRef.nativeElement, ...(ngDevMode ? [{ debugName: "containerEl" }] : /* istanbul ignore next */ []));
625
706
  this.graceArea = useGraceArea(this.triggerEl, this.containerEl);
626
- /**
627
- * An element to position the popup against. Defaults to the trigger.
628
- */
629
- this.anchor = input(...(ngDevMode ? [undefined, { debugName: "anchor" }] : /* istanbul ignore next */ []));
630
- /**
631
- * The preferred side of the trigger to render against when open.
632
- */
633
- this.side = input('bottom', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
634
- /**
635
- * Distance between the trigger and the popup in pixels.
636
- */
637
- this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
638
- /**
639
- * How to align the popup relative to the specified side.
640
- */
641
- this.align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
642
- /**
643
- * An offset in pixels from the `start` or `end` alignment options.
644
- */
645
- this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
646
- /**
647
- * Minimum distance to maintain between the arrow and the edges of the popup.
648
- */
649
- this.arrowPadding = input(5, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
650
- /**
651
- * Whether to override side and alignment preferences to prevent collisions.
652
- */
653
- this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
654
- /**
655
- * The element used as the collision boundary.
656
- */
657
- this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
658
- /**
659
- * Distance in pixels from the boundary edges where collision detection should occur.
660
- */
661
- this.collisionPadding = input(5, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
662
- /**
663
- * The sticky behavior on the alignment axis.
664
- */
665
- this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
666
- /**
667
- * Whether to hide the popup when the trigger becomes fully occluded.
668
- */
669
- this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
670
- /**
671
- * The CSS position strategy used by Floating UI.
672
- */
673
- this.positionStrategy = input('fixed', ...(ngDevMode ? [{ debugName: "positionStrategy" }] : /* istanbul ignore next */ []));
674
- /**
675
- * Whether to update position on every animation frame.
676
- */
677
- this.updatePositionStrategy = input('always', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
678
- /**
679
- * Emits when the popup has been placed.
680
- */
681
- this.placed = outputFromObservable(outputToObservable(inject(RdxPopperContentWrapper).placed));
682
707
  effect(() => this.triggerEl.set(this.rootContext.trigger() ?? null));
683
708
  this.graceArea.onPointerExit(() => {
684
709
  this.rootContext.closeOnHover();
685
710
  });
686
711
  }
687
712
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
688
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPopoverPositioner, isStandalone: true, selector: "[rdxPopoverPositioner]", inputs: { anchor: { classPropertyName: "anchor", publicName: "anchor", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, sideOffset: { classPropertyName: "sideOffset", publicName: "sideOffset", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, alignOffset: { classPropertyName: "alignOffset", publicName: "alignOffset", isSignal: true, isRequired: false, transformFunction: null }, arrowPadding: { classPropertyName: "arrowPadding", publicName: "arrowPadding", isSignal: true, isRequired: false, transformFunction: null }, avoidCollisions: { classPropertyName: "avoidCollisions", publicName: "avoidCollisions", isSignal: true, isRequired: false, transformFunction: null }, collisionBoundary: { classPropertyName: "collisionBoundary", publicName: "collisionBoundary", isSignal: true, isRequired: false, transformFunction: null }, collisionPadding: { classPropertyName: "collisionPadding", publicName: "collisionPadding", isSignal: true, isRequired: false, transformFunction: null }, sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null }, hideWhenDetached: { classPropertyName: "hideWhenDetached", publicName: "hideWhenDetached", isSignal: true, isRequired: false, transformFunction: null }, positionStrategy: { classPropertyName: "positionStrategy", publicName: "positionStrategy", isSignal: true, isRequired: false, transformFunction: null }, updatePositionStrategy: { classPropertyName: "updatePositionStrategy", publicName: "updatePositionStrategy", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { placed: "placed" }, host: { properties: { "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-anchor-hidden": "wrapper.anchorHidden() ? \"\" : undefined", "attr.data-align": "wrapper.placedAlign()", "attr.data-side": "wrapper.placedSide()", "attr.data-instant": "rootContext.instant() ? \"\" : undefined", "style": "{\n '--anchor-width': 'var(--radix-popper-anchor-width)',\n '--anchor-height': 'var(--radix-popper-anchor-height)',\n '--available-width': 'var(--radix-popper-available-width)',\n '--available-height': 'var(--radix-popper-available-height)',\n '--positioner-width': 'var(--radix-popper-content-wrapper-width)',\n '--positioner-height': 'var(--radix-popper-content-wrapper-height)',\n '--transform-origin': 'var(--radix-popper-transform-origin)',\n '--radix-popover-content-transform-origin': 'var(--radix-popper-transform-origin)',\n '--radix-popover-content-available-width': 'var(--radix-popper-available-width)',\n '--radix-popover-content-available-height': 'var(--radix-popper-available-height)',\n '--radix-popover-trigger-width': 'var(--radix-popper-anchor-width)',\n '--radix-popover-trigger-height': 'var(--radix-popper-anchor-height)'\n }" } }, providers: [
713
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPopoverPositioner, isStandalone: true, selector: "[rdxPopoverPositioner]", host: { properties: { "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-instant": "rootContext.instant() ? \"\" : undefined", "style": "legacyVars" } }, providers: [
714
+ ...provideRdxPopperContentWrapper(RdxPopoverPositioner),
689
715
  provideRdxPopperContentConfig({ arrowPadding: 5, collisionPadding: 5, updatePositionStrategy: 'always' })
690
- ], hostDirectives: [{ directive: i1.RdxPopperContentWrapper, inputs: ["anchor", "anchor", "side", "side", "sideOffset", "sideOffset", "align", "align", "alignOffset", "alignOffset", "arrowPadding", "arrowPadding", "avoidCollisions", "avoidCollisions", "collisionBoundary", "collisionBoundary", "collisionPadding", "collisionPadding", "sticky", "sticky", "hideWhenDetached", "hideWhenDetached", "positionStrategy", "positionStrategy", "updatePositionStrategy", "updatePositionStrategy"] }], ngImport: i0 }); }
716
+ ], usesInheritance: true, ngImport: i0 }); }
691
717
  }
692
718
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverPositioner, decorators: [{
693
719
  type: Directive,
694
720
  args: [{
695
721
  selector: '[rdxPopoverPositioner]',
696
722
  providers: [
723
+ ...provideRdxPopperContentWrapper(RdxPopoverPositioner),
697
724
  provideRdxPopperContentConfig({ arrowPadding: 5, collisionPadding: 5, updatePositionStrategy: 'always' })
698
725
  ],
699
- hostDirectives: [
700
- {
701
- directive: RdxPopperContentWrapper,
702
- inputs: [
703
- 'anchor',
704
- 'side',
705
- 'sideOffset',
706
- 'align',
707
- 'alignOffset',
708
- 'arrowPadding',
709
- 'avoidCollisions',
710
- 'collisionBoundary',
711
- 'collisionPadding',
712
- 'sticky',
713
- 'hideWhenDetached',
714
- 'positionStrategy',
715
- 'updatePositionStrategy'
716
- ]
717
- }
718
- ],
719
726
  host: {
720
727
  '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
721
728
  '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
722
- '[attr.data-anchor-hidden]': 'wrapper.anchorHidden() ? "" : undefined',
723
- '[attr.data-align]': 'wrapper.placedAlign()',
724
- '[attr.data-side]': 'wrapper.placedSide()',
725
729
  '[attr.data-instant]': 'rootContext.instant() ? "" : undefined',
726
- '[style]': `{
727
- '--anchor-width': 'var(--radix-popper-anchor-width)',
728
- '--anchor-height': 'var(--radix-popper-anchor-height)',
729
- '--available-width': 'var(--radix-popper-available-width)',
730
- '--available-height': 'var(--radix-popper-available-height)',
731
- '--positioner-width': 'var(--radix-popper-content-wrapper-width)',
732
- '--positioner-height': 'var(--radix-popper-content-wrapper-height)',
733
- '--transform-origin': 'var(--radix-popper-transform-origin)',
734
- '--radix-popover-content-transform-origin': 'var(--radix-popper-transform-origin)',
735
- '--radix-popover-content-available-width': 'var(--radix-popper-available-width)',
736
- '--radix-popover-content-available-height': 'var(--radix-popper-available-height)',
737
- '--radix-popover-trigger-width': 'var(--radix-popper-anchor-width)',
738
- '--radix-popover-trigger-height': 'var(--radix-popper-anchor-height)'
739
- }`
730
+ // `data-side`/`data-align`/`data-anchor-hidden` and the unified `--anchor-*`/`--available-*`/
731
+ // `--transform-origin` vars come from the inherited wrapper (ADR 0012); only the deprecated
732
+ // `--radix-popover-*` aliases remain, for one release of back-compat.
733
+ '[style]': 'legacyVars'
740
734
  }
741
735
  }]
742
- }], ctorParameters: () => [], propDecorators: { anchor: [{ type: i0.Input, args: [{ isSignal: true, alias: "anchor", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], sideOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "sideOffset", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], alignOffset: [{ type: i0.Input, args: [{ isSignal: true, alias: "alignOffset", required: false }] }], arrowPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "arrowPadding", required: false }] }], avoidCollisions: [{ type: i0.Input, args: [{ isSignal: true, alias: "avoidCollisions", required: false }] }], collisionBoundary: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionBoundary", required: false }] }], collisionPadding: [{ type: i0.Input, args: [{ isSignal: true, alias: "collisionPadding", required: false }] }], sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }], hideWhenDetached: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideWhenDetached", required: false }] }], positionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "positionStrategy", required: false }] }], updatePositionStrategy: [{ type: i0.Input, args: [{ isSignal: true, alias: "updatePositionStrategy", required: false }] }], placed: [{ type: i0.Output, args: ["placed"] }] } });
736
+ }], ctorParameters: () => [] });
743
737
 
744
738
  /**
745
739
  * An accessible title for the popover.
@@ -771,6 +765,8 @@ class RdxPopoverTrigger {
771
765
  constructor() {
772
766
  this.parentRootContext = injectRdxPopoverRootContext(true);
773
767
  this.elementRef = inject(ElementRef);
768
+ /** Pointer type of the most recent `pointerdown`, used to detect a touch open (ADR 0016 §3). */
769
+ this.lastPointerType = '';
774
770
  /**
775
771
  * Associates this trigger with a detached popover root.
776
772
  */
@@ -818,6 +814,9 @@ class RdxPopoverTrigger {
818
814
  if (this.disabled()) {
819
815
  return;
820
816
  }
817
+ // Record whether this open is a touch tap (ADR 0016 §3). `detail === 0` is a keyboard-activated
818
+ // click (no preceding pointerdown), which must read non-touch regardless of the last pointer type.
819
+ this.rootContext()?.setOpenedByTouch(event.detail !== 0 && this.lastPointerType === 'touch');
821
820
  this.rootContext()?.setPointerDownOnTrigger(false);
822
821
  if (this.handle()) {
823
822
  this.handle().toggle(this.triggerId(), event);
@@ -840,14 +839,15 @@ class RdxPopoverTrigger {
840
839
  }
841
840
  this.rootContext()?.cancelHoverOpen();
842
841
  }
843
- handlePointerDown() {
842
+ handlePointerDown(event) {
843
+ this.lastPointerType = event.pointerType;
844
844
  this.rootContext()?.setPointerDownOnTrigger(true);
845
845
  }
846
846
  handlePointerUp() {
847
847
  this.rootContext()?.setPointerDownOnTrigger(false);
848
848
  }
849
849
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
850
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPopoverTrigger, isStandalone: true, selector: "button[rdxPopoverTrigger]", inputs: { handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null }, payload: { classPropertyName: "payload", publicName: "payload", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", 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: { attributes: { "type": "button" }, listeners: { "click": "handleClick($event)", "pointerenter": "handlePointerEnter($event)", "pointerleave": "handlePointerLeave($event)", "pointerdown": "handlePointerDown()", "pointerup": "handlePointerUp()", "pointercancel": "handlePointerUp()" }, properties: { "attr.aria-controls": "rootContext()?.contentId", "attr.aria-expanded": "isOpen()", "attr.aria-haspopup": "\"dialog\"", "attr.data-state": "isOpen() ? \"open\" : \"closed\"", "attr.data-popup-open": "isOpen() ? \"\" : undefined", "attr.data-pressed": "isPressed() ? \"\" : undefined", "attr.disabled": "disabled() ? \"\" : undefined", "id": "triggerId()" } }, hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
850
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPopoverTrigger, isStandalone: true, selector: "button[rdxPopoverTrigger]", inputs: { handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null }, payload: { classPropertyName: "payload", publicName: "payload", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", 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: { attributes: { "type": "button" }, listeners: { "click": "handleClick($event)", "pointerenter": "handlePointerEnter($event)", "pointerleave": "handlePointerLeave($event)", "pointerdown": "handlePointerDown($event)", "pointerup": "handlePointerUp()", "pointercancel": "handlePointerUp()" }, properties: { "attr.aria-controls": "rootContext()?.contentId", "attr.aria-expanded": "isOpen()", "attr.aria-haspopup": "\"dialog\"", "attr.data-state": "isOpen() ? \"open\" : \"closed\"", "attr.data-popup-open": "isOpen() ? \"\" : undefined", "attr.data-pressed": "isPressed() ? \"\" : undefined", "attr.disabled": "disabled() ? \"\" : undefined", "id": "triggerId()" } }, hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
851
851
  }
852
852
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverTrigger, decorators: [{
853
853
  type: Directive,
@@ -867,7 +867,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
867
867
  '(click)': 'handleClick($event)',
868
868
  '(pointerenter)': 'handlePointerEnter($event)',
869
869
  '(pointerleave)': 'handlePointerLeave($event)',
870
- '(pointerdown)': 'handlePointerDown()',
870
+ '(pointerdown)': 'handlePointerDown($event)',
871
871
  '(pointerup)': 'handlePointerUp()',
872
872
  '(pointercancel)': 'handlePointerUp()'
873
873
  }
@@ -1070,8 +1070,8 @@ function createRdxPopoverHandle() {
1070
1070
  const popoverImports = [
1071
1071
  RdxPopoverRoot,
1072
1072
  RdxPopoverTrigger,
1073
- RdxPopoverPortalPresence,
1074
1073
  RdxPopoverPortal,
1074
+ RdxPopoverPortalMisuseGuard,
1075
1075
  RdxPopoverBackdrop,
1076
1076
  RdxPopoverPositioner,
1077
1077
  RdxPopoverPopup,
@@ -1085,8 +1085,8 @@ class RdxPopoverModule {
1085
1085
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
1086
1086
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: RdxPopoverModule, imports: [RdxPopoverRoot,
1087
1087
  RdxPopoverTrigger,
1088
- RdxPopoverPortalPresence,
1089
1088
  RdxPopoverPortal,
1089
+ RdxPopoverPortalMisuseGuard,
1090
1090
  RdxPopoverBackdrop,
1091
1091
  RdxPopoverPositioner,
1092
1092
  RdxPopoverPopup,
@@ -1096,8 +1096,8 @@ class RdxPopoverModule {
1096
1096
  RdxPopoverClose,
1097
1097
  RdxPopoverViewport], exports: [RdxPopoverRoot,
1098
1098
  RdxPopoverTrigger,
1099
- RdxPopoverPortalPresence,
1100
1099
  RdxPopoverPortal,
1100
+ RdxPopoverPortalMisuseGuard,
1101
1101
  RdxPopoverBackdrop,
1102
1102
  RdxPopoverPositioner,
1103
1103
  RdxPopoverPopup,
@@ -1120,5 +1120,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
1120
1120
  * Generated bundle index. Do not edit.
1121
1121
  */
1122
1122
 
1123
- export { RdxPopoverArrow, RdxPopoverBackdrop, RdxPopoverClose, RdxPopoverDescription, RdxPopoverHandle, RdxPopoverModule, RdxPopoverPopup, RdxPopoverPortal, RdxPopoverPortalPresence, RdxPopoverPositioner, RdxPopoverRoot, RdxPopoverTitle, RdxPopoverTrigger, RdxPopoverViewport, createRdxPopoverHandle, injectRdxPopoverRootContext, popoverImports, provideRdxPopoverRootContext };
1123
+ export { RdxPopoverArrow, RdxPopoverBackdrop, RdxPopoverClose, RdxPopoverDescription, RdxPopoverHandle, RdxPopoverModule, RdxPopoverPopup, RdxPopoverPortal, RdxPopoverPortalMisuseGuard, RdxPopoverPositioner, RdxPopoverRoot, RdxPopoverTitle, RdxPopoverTrigger, RdxPopoverViewport, createRdxPopoverHandle, injectRdxPopoverRootContext, popoverImports, provideRdxPopoverRootContext };
1124
1124
  //# sourceMappingURL=radix-ng-primitives-popover.mjs.map