@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,15 +1,13 @@
1
1
  import * as i0 from '@angular/core';
2
- import { inject, DestroyRef, signal, model, input, booleanAttribute, output, computed, effect, untracked, Directive, ElementRef, numberAttribute, afterNextRender, NgModule } from '@angular/core';
2
+ import { inject, DestroyRef, ElementRef, signal, model, input, booleanAttribute, 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, useGraceArea } from '@radix-ng/primitives/core';
6
- 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';
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, RdxFloatingNodeRegistration, rdxDevError, useGraceArea, rdxCheckTriggerElement } from '@radix-ng/primitives/core';
7
+ import { RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
9
8
  import * as i1$1 from '@radix-ng/primitives/portal';
10
- import { RdxPortal } from '@radix-ng/primitives/portal';
11
- import * as i1$2 from '@radix-ng/primitives/presence';
12
- import { provideRdxPresenceContext, RdxPresenceDirective } from '@radix-ng/primitives/presence';
9
+ import { RdxPortalPresence } from '@radix-ng/primitives/portal';
10
+ import { provideRdxPresenceContext } from '@radix-ng/primitives/presence';
13
11
 
14
12
  const context = () => contextFor(inject(RdxPreviewCardRoot));
15
13
  const [injectRdxPreviewCardRootContext, provideRdxPreviewCardRootContext] = createContext('RdxPreviewCardRootContext', 'components/preview-card');
@@ -20,6 +18,15 @@ class RdxPreviewCardRoot {
20
18
  constructor() {
21
19
  this.popper = inject(RdxPopper);
22
20
  this.destroyRef = inject(DestroyRef);
21
+ /**
22
+ * Per-popup floating root context (ADR 0015) — the shared store the popup's dismissal capability
23
+ * reads (`open`, `triggers`, the reference/floating elements). The tree node is registered by the
24
+ * popup; this context exists independently so dismissal can read `open()`.
25
+ */
26
+ this.floatingContext = createFloatingRootContext({
27
+ ownerDocument: inject(ElementRef).nativeElement.ownerDocument,
28
+ open: () => this.open()
29
+ });
23
30
  /** Shared open/close transition state machine (completes on the real animationend). */
24
31
  this.transition = useTransitionStatus((open) => {
25
32
  this.instant.set(false);
@@ -58,11 +65,13 @@ class RdxPreviewCardRoot {
58
65
  this.triggers = signal([], ...(ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []));
59
66
  this.payload = signal(undefined, ...(ngDevMode ? [{ debugName: "payload" }] : /* istanbul ignore next */ []));
60
67
  this.isPointerDownOnTrigger = signal(false, ...(ngDevMode ? [{ debugName: "isPointerDownOnTrigger" }] : /* istanbul ignore next */ []));
68
+ this.preventUnmountOnClose = signal(false, ...(ngDevMode ? [{ debugName: "preventUnmountOnClose" }] : /* istanbul ignore next */ []));
61
69
  this.onOpenChange = output();
62
70
  this.onOpenChangeComplete = output();
63
71
  this.registeredTriggers = new Map();
64
72
  this.viewportTriggerChange = new Set();
65
73
  this.state = computed(() => (this.open() ? 'open' : 'closed'), ...(ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []));
74
+ this.present = computed(() => this.open() || this.preventUnmountOnClose(), ...(ngDevMode ? [{ debugName: "present" }] : /* istanbul ignore next */ []));
66
75
  let previousOpen = this.open();
67
76
  effect(() => {
68
77
  const defaultOpen = this.defaultOpen();
@@ -96,6 +105,14 @@ class RdxPreviewCardRoot {
96
105
  }
97
106
  });
98
107
  effect(() => this.popper.anchorOverride.set(this.trigger()));
108
+ // Sync the dismissal reference (the active trigger) so an outside-press on the trigger counts
109
+ // as "inside" and never dismisses (ADR 0015).
110
+ effect(() => this.floatingContext.setReferenceElement(this.trigger() ?? null));
111
+ effect(() => {
112
+ if (this.open() && this.preventUnmountOnClose()) {
113
+ this.preventUnmountOnClose.set(false);
114
+ }
115
+ });
99
116
  this.destroyRef.onDestroy(() => {
100
117
  this.clearHoverTimers();
101
118
  if (this.instantFrame !== undefined) {
@@ -105,10 +122,25 @@ class RdxPreviewCardRoot {
105
122
  }
106
123
  show(trigger = this.trigger(), payload, triggerId, reason = 'none', event = new Event('preview-card.open-change'), fromHover = false) {
107
124
  this.clearHoverTimers();
108
- this.isHoverActive.set(fromHover);
109
- this.openChangeReason.set(reason);
110
125
  const previousTrigger = this.trigger();
111
126
  const changedTriggerWhileOpen = this.open() && previousTrigger !== trigger;
127
+ const changed = !this.open() || previousTrigger !== trigger;
128
+ if (!changed) {
129
+ this.isHoverActive.set(fromHover);
130
+ this.openChangeReason.set(reason);
131
+ if (triggerId !== undefined) {
132
+ this.triggerId.set(triggerId);
133
+ }
134
+ this.payload.set(payload);
135
+ return;
136
+ }
137
+ const change = this.createOpenChangeEvent(true, reason, event, trigger, triggerId ?? this.triggerId());
138
+ this.onOpenChange.emit(change.payload);
139
+ if (change.eventDetails.isCanceled()) {
140
+ return;
141
+ }
142
+ this.isHoverActive.set(fromHover);
143
+ this.openChangeReason.set(reason);
112
144
  this.instant.set(changedTriggerWhileOpen || reason === 'trigger-focus');
113
145
  if (changedTriggerWhileOpen) {
114
146
  this.scheduleInstantReset();
@@ -123,22 +155,26 @@ class RdxPreviewCardRoot {
123
155
  this.triggerId.set(triggerId);
124
156
  }
125
157
  this.payload.set(payload);
126
- const changed = !this.open() || previousTrigger !== trigger;
158
+ this.preventUnmountOnClose.set(false);
127
159
  this.open.set(true);
128
- if (changed) {
129
- this.emitOpenChange(true, reason, event);
130
- }
160
+ this.floatingContext.events.emit('openchange', { open: true, reason, event: change.eventDetails.event });
131
161
  }
132
162
  close(reason = 'none', event = new Event('preview-card.open-change')) {
133
163
  this.clearHoverTimers();
134
- this.isHoverActive.set(false);
135
164
  if (!this.open()) {
136
165
  return;
137
166
  }
167
+ const change = this.createOpenChangeEvent(false, reason, event, this.trigger(), this.triggerId());
168
+ this.onOpenChange.emit(change.payload);
169
+ if (change.eventDetails.isCanceled()) {
170
+ return;
171
+ }
172
+ this.isHoverActive.set(false);
138
173
  this.instant.set(reason !== 'none' && reason !== 'trigger-hover');
139
174
  this.openChangeReason.set(reason);
175
+ this.preventUnmountOnClose.set(change.shouldPreventUnmountOnClose());
140
176
  this.open.set(false);
141
- this.emitOpenChange(false, reason, event);
177
+ this.floatingContext.events.emit('openchange', { open: false, reason, event: change.eventDetails.event });
142
178
  }
143
179
  toggle(triggerId, trigger, payload, event) {
144
180
  this.clearHoverTimers();
@@ -178,6 +214,7 @@ class RdxPreviewCardRoot {
178
214
  registerTrigger(id, trigger, payload) {
179
215
  this.registeredTriggers.set(id, { element: trigger, payload });
180
216
  this.triggers.update((triggers) => (triggers.includes(trigger) ? triggers : [...triggers, trigger]));
217
+ this.floatingContext.triggers.add(trigger);
181
218
  if (this.triggerId() === id) {
182
219
  this.trigger.set(trigger);
183
220
  this.payload.set(payload());
@@ -191,6 +228,7 @@ class RdxPreviewCardRoot {
191
228
  this.registeredTriggers.delete(id);
192
229
  }
193
230
  this.triggers.update((triggers) => triggers.filter((candidate) => candidate !== trigger));
231
+ this.floatingContext.triggers.delete(trigger);
194
232
  if (this.destroyRef.destroyed) {
195
233
  return;
196
234
  }
@@ -236,14 +274,20 @@ class RdxPreviewCardRoot {
236
274
  this.trigger.set(trigger.element);
237
275
  this.payload.set(trigger.payload());
238
276
  }
239
- emitOpenChange(open, reason, event) {
240
- this.onOpenChange.emit({
241
- open,
242
- triggerId: this.triggerId(),
243
- trigger: this.trigger(),
244
- reason,
245
- event
246
- });
277
+ createOpenChangeEvent(open, reason, event, trigger, triggerId) {
278
+ const change = createCancelableChangeEventDetails(reason, event, trigger);
279
+ return {
280
+ eventDetails: change.eventDetails,
281
+ shouldPreventUnmountOnClose: change.shouldPreventUnmountOnClose,
282
+ payload: {
283
+ open,
284
+ triggerId,
285
+ trigger: change.eventDetails.trigger,
286
+ reason: change.eventDetails.reason,
287
+ event: change.eventDetails.event,
288
+ eventDetails: change.eventDetails
289
+ }
290
+ };
247
291
  }
248
292
  clearHoverTimers() {
249
293
  this.clearOpenTimer();
@@ -273,14 +317,22 @@ class RdxPreviewCardRoot {
273
317
  });
274
318
  }
275
319
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardRoot, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
276
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPreviewCardRoot, isStandalone: true, selector: "[rdxPreviewCardRoot]", 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 }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", triggerId: "triggerIdChange", onOpenChange: "onOpenChange", onOpenChangeComplete: "onOpenChangeComplete" }, providers: [provideRdxPreviewCardRootContext(context)], exportAs: ["rdxPreviewCardRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
320
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPreviewCardRoot, isStandalone: true, selector: "[rdxPreviewCardRoot]", 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 }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", triggerId: "triggerIdChange", onOpenChange: "onOpenChange", onOpenChangeComplete: "onOpenChangeComplete" }, providers: [
321
+ provideRdxPreviewCardRootContext(context),
322
+ provideFloatingTree(),
323
+ provideFloatingRootContext(() => inject(RdxPreviewCardRoot).floatingContext)
324
+ ], exportAs: ["rdxPreviewCardRoot"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
277
325
  }
278
326
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardRoot, decorators: [{
279
327
  type: Directive,
280
328
  args: [{
281
329
  selector: '[rdxPreviewCardRoot]',
282
330
  exportAs: 'rdxPreviewCardRoot',
283
- providers: [provideRdxPreviewCardRootContext(context)],
331
+ providers: [
332
+ provideRdxPreviewCardRootContext(context),
333
+ provideFloatingTree(),
334
+ provideFloatingRootContext(() => inject(RdxPreviewCardRoot).floatingContext)
335
+ ],
284
336
  hostDirectives: [RdxPopper]
285
337
  }]
286
338
  }], 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 }] }], handle: [{ type: i0.Input, args: [{ isSignal: true, alias: "handle", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }], onOpenChangeComplete: [{ type: i0.Output, args: ["onOpenChangeComplete"] }] } });
@@ -288,6 +340,7 @@ function contextFor(root) {
288
340
  return {
289
341
  contentId: root.contentId,
290
342
  isOpen: root.open.asReadonly(),
343
+ present: root.present,
291
344
  trigger: root.trigger.asReadonly(),
292
345
  triggers: root.triggers.asReadonly(),
293
346
  payload: root.payload.asReadonly(),
@@ -367,79 +420,73 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
367
420
 
368
421
  /**
369
422
  * A container for the preview-card contents.
423
+ *
424
+ * **ADR 0015 migration** onto the new floating dismissal engine (dismissal-only — a preview-card has
425
+ * no focus manager, ADR 0017 §1). Escape, an outside press, and a focus-out all close it (the legacy's
426
+ * trigger-press preventDefault is now automatic: the trigger is the registered reference, so a press on
427
+ * it is "inside" and never fires `pointerDownOutside`). A focus-out while a pointer is held on the
428
+ * trigger is still vetoed.
370
429
  */
371
430
  class RdxPreviewCardPopup {
372
431
  constructor() {
373
432
  this.rootContext = injectRdxPreviewCardRootContext();
374
- this.dismissableLayer = inject(RdxDismissableLayer);
433
+ this.host = inject(ElementRef).nativeElement;
434
+ this.floatingContext = inject(RDX_FLOATING_ROOT_CONTEXT);
435
+ this.registration = inject(RDX_FLOATING_REGISTRATION, { optional: true });
375
436
  this.wrapper = inject(RdxPopperContentWrapper, { optional: true });
376
437
  this.align = computed(() => this.wrapper?.placedAlign(), ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
377
438
  this.side = computed(() => this.wrapper?.placedSide(), ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
378
- this.dismissDetails = {
379
- reason: 'none',
380
- event: new Event('preview-card.dismiss')
381
- };
382
439
  /**
383
440
  * Event handler called when the escape key is down. Can be prevented.
384
441
  */
385
- this.escapeKeyDown = outputFromObservable(outputToObservable(this.dismissableLayer.escapeKeyDown));
442
+ this.escapeKeyDown = output();
386
443
  /**
387
444
  * Event handler called when a pointerdown event happens outside of the popup. Can be prevented.
388
445
  */
389
- this.pointerDownOutside = outputFromObservable(outputToObservable(this.dismissableLayer.pointerDownOutside));
446
+ this.pointerDownOutside = output();
390
447
  /**
391
448
  * Event handler called when focus moves outside of the popup. Can be prevented.
392
449
  */
393
- this.focusOutside = outputFromObservable(outputToObservable(this.dismissableLayer.focusOutside));
450
+ this.focusOutside = output();
394
451
  /**
395
452
  * Event handler called when an interaction happens outside of the popup. Can be prevented.
396
453
  */
397
- this.interactOutside = outputFromObservable(outputToObservable(this.dismissableLayer.interactOutside));
398
- const unregisterTransitionElement = this.rootContext.registerTransitionElement(inject(ElementRef).nativeElement);
399
- inject(DestroyRef).onDestroy(() => {
400
- unregisterTransitionElement();
401
- });
402
- this.dismissableLayer.pointerDownOutside.subscribe((event) => {
403
- this.dismissDetails = { reason: 'outside-press', event };
404
- if (this.rootContext.triggers().some((trigger) => trigger.contains(event.target))) {
405
- event.preventDefault();
406
- }
407
- });
408
- this.dismissableLayer.focusOutside.subscribe((event) => {
409
- this.dismissDetails = { reason: 'none', event };
410
- if (this.rootContext.isPointerDownOnTrigger()) {
411
- event.preventDefault();
454
+ this.interactOutside = output();
455
+ this.floatingContext.setFloatingElement(this.host);
456
+ const unregisterTransitionElement = this.rootContext.registerTransitionElement(this.host);
457
+ inject(DestroyRef).onDestroy(unregisterTransitionElement);
458
+ new RdxDismiss(this.floatingContext, () => this.registration?.node() ?? null, {
459
+ escapeKey: () => true,
460
+ outsidePress: () => true,
461
+ focusOutside: () => true,
462
+ onEscapeKeyDown: (event) => this.escapeKeyDown.emit(event),
463
+ onPointerDownOutside: (event) => {
464
+ this.pointerDownOutside.emit(event);
465
+ this.interactOutside.emit(event);
466
+ },
467
+ onFocusOutside: (event) => {
468
+ // A focus-out triggered by a pointer press still in flight on the trigger must not close
469
+ // the card (the toggle handles it) — veto it like the legacy did.
470
+ if (this.rootContext.isPointerDownOnTrigger()) {
471
+ event.preventDefault();
472
+ }
473
+ this.focusOutside.emit(event);
474
+ this.interactOutside.emit(event);
475
+ },
476
+ onDismiss: (reason, event) => {
477
+ const mapped = reason === 'escape-key' ? 'escape-key' : reason === 'outside-press' ? 'outside-press' : 'none';
478
+ this.rootContext.close(mapped, event);
412
479
  }
413
480
  });
414
- this.dismissableLayer.escapeKeyDown.subscribe((event) => {
415
- this.dismissDetails = { reason: 'escape-key', event };
416
- });
417
- this.dismissableLayer.dismiss.subscribe(() => {
418
- this.rootContext.close(this.dismissDetails.reason, this.dismissDetails.event);
419
- this.dismissDetails = { reason: 'none', event: new Event('preview-card.dismiss') };
420
- });
421
481
  }
422
482
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPopup, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
423
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPreviewCardPopup, isStandalone: true, selector: "[rdxPreviewCardPopup]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside", focusOutside: "focusOutside", interactOutside: "interactOutside" }, host: { listeners: { "pointerenter": "rootContext.cancelHoverClose()" }, 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\"", "attr.data-align": "align()", "attr.data-side": "side()", "id": "rootContext.contentId" } }, providers: [
424
- provideRdxDismissableLayerConfig(() => {
425
- return {
426
- disableOutsidePointerEvents: signal(false)
427
- };
428
- })
429
- ], hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxDismissableLayer }], ngImport: i0 }); }
483
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPreviewCardPopup, isStandalone: true, selector: "[rdxPreviewCardPopup]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside", focusOutside: "focusOutside", interactOutside: "interactOutside" }, host: { listeners: { "pointerenter": "rootContext.cancelHoverClose()" }, 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\"", "attr.data-align": "align()", "attr.data-side": "side()", "id": "rootContext.contentId" } }, hostDirectives: [{ directive: i1.RdxPopperContent }, { directive: i2.RdxFloatingNodeRegistration }], ngImport: i0 }); }
430
484
  }
431
485
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPopup, decorators: [{
432
486
  type: Directive,
433
487
  args: [{
434
488
  selector: '[rdxPreviewCardPopup]',
435
- hostDirectives: [RdxPopperContent, RdxDismissableLayer],
436
- providers: [
437
- provideRdxDismissableLayerConfig(() => {
438
- return {
439
- disableOutsidePointerEvents: signal(false)
440
- };
441
- })
442
- ],
489
+ hostDirectives: [RdxPopperContent, RdxFloatingNodeRegistration],
443
490
  host: {
444
491
  '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
445
492
  '[attr.data-ending-style]': 'rootContext.transitionStatus() === "ending" ? "" : undefined',
@@ -456,191 +503,97 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
456
503
  }], ctorParameters: () => [], propDecorators: { escapeKeyDown: [{ type: i0.Output, args: ["escapeKeyDown"] }], pointerDownOutside: [{ type: i0.Output, args: ["pointerDownOutside"] }], focusOutside: [{ type: i0.Output, args: ["focusOutside"] }], interactOutside: [{ type: i0.Output, args: ["interactOutside"] }] } });
457
504
 
458
505
  /**
459
- * Moves the preview-card to a different part of the DOM.
506
+ * Structural directive that teleports the preview-card content into a container (default
507
+ * `document.body`) while the card is open, and keeps it mounted until any CSS exit `@keyframes`
508
+ * finishes.
509
+ *
510
+ * Apply it with the `*` microsyntax on the positioner —
511
+ * `<div *rdxPreviewCardPortal rdxPreviewCardPositioner>` — or as an explicit
512
+ * `<ng-template rdxPreviewCardPortal>`. For a custom container use the explicit form with `[container]`.
460
513
  */
461
514
  class RdxPreviewCardPortal {
462
- constructor() {
463
- this.rootContext = injectRdxPreviewCardRootContext();
464
- /**
465
- * Optional container to portal the content into. Defaults to `document.body`.
466
- */
467
- this.container = input(...(ngDevMode ? [undefined, { debugName: "container" }] : /* istanbul ignore next */ []));
468
- }
469
515
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
470
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPreviewCardPortal, isStandalone: true, selector: "[rdxPreviewCardPortal]", 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 }); }
516
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPreviewCardPortal, isStandalone: true, selector: "ng-template[rdxPreviewCardPortal]", providers: [provideRdxPresenceContext(() => ({ present: injectRdxPreviewCardRootContext().present }))], exportAs: ["rdxPreviewCardPortal"], hostDirectives: [{ directive: i1$1.RdxPortalPresence, inputs: ["container", "container"] }], ngImport: i0 }); }
471
517
  }
472
518
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPortal, decorators: [{
473
519
  type: Directive,
474
520
  args: [{
475
- selector: '[rdxPreviewCardPortal]',
476
- hostDirectives: [
477
- {
478
- directive: RdxPortal,
479
- inputs: ['container']
480
- }
481
- ],
482
- host: {
483
- '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
484
- '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
485
- '[attr.data-state]': 'rootContext.isOpen() ? "open" : "closed"'
486
- }
521
+ selector: 'ng-template[rdxPreviewCardPortal]',
522
+ exportAs: 'rdxPreviewCardPortal',
523
+ hostDirectives: [{ directive: RdxPortalPresence, inputs: ['container'] }],
524
+ providers: [provideRdxPresenceContext(() => ({ present: injectRdxPreviewCardRootContext().present }))]
487
525
  }]
488
- }], propDecorators: { container: [{ type: i0.Input, args: [{ isSignal: true, alias: "container", required: false }] }] } });
489
-
526
+ }] });
490
527
  /**
491
- * Mounts the portal while the preview-card is open and waits for CSS exit keyframes before unmounting.
528
+ * Dev-mode guard: `rdxPreviewCardPortal` used to be an attribute directive on a `<div>`. It is now
529
+ * structural, so the old `<div rdxPreviewCardPortal>` markup would silently stop portaling — fail
530
+ * loudly instead.
492
531
  */
493
- class RdxPreviewCardPortalPresence {
494
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPortalPresence, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
495
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPreviewCardPortalPresence, isStandalone: true, selector: "ng-template[rdxPreviewCardPortalPresence]", providers: [
496
- provideRdxPresenceContext(() => {
497
- const context = injectRdxPreviewCardRootContext();
498
- return { present: context.isOpen };
499
- })
500
- ], hostDirectives: [{ directive: i1$2.RdxPresenceDirective }], ngImport: i0 }); }
532
+ class RdxPreviewCardPortalMisuseGuard {
533
+ constructor() {
534
+ if (isDevMode()) {
535
+ rdxDevError('preview-card/portal-on-element', '`rdxPreviewCardPortal` is now a structural directive. ' +
536
+ 'Use `*rdxPreviewCardPortal` on the positioner element or `<ng-template rdxPreviewCardPortal>`. ' +
537
+ 'rdxPreviewCardPortalPresence has been removed.', 'components/preview-card');
538
+ }
539
+ }
540
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPortalMisuseGuard, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
541
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPreviewCardPortalMisuseGuard, isStandalone: true, selector: "[rdxPreviewCardPortal]:not(ng-template)", ngImport: i0 }); }
501
542
  }
502
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPortalPresence, decorators: [{
543
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPortalMisuseGuard, decorators: [{
503
544
  type: Directive,
504
545
  args: [{
505
- selector: 'ng-template[rdxPreviewCardPortalPresence]',
506
- hostDirectives: [RdxPresenceDirective],
507
- providers: [
508
- provideRdxPresenceContext(() => {
509
- const context = injectRdxPreviewCardRootContext();
510
- return { present: context.isOpen };
511
- })
512
- ]
546
+ selector: '[rdxPreviewCardPortal]:not(ng-template)'
513
547
  }]
514
- }] });
548
+ }], ctorParameters: () => [] });
515
549
 
516
550
  /**
517
551
  * Positions the preview-card against its trigger.
552
+ *
553
+ * A "thin" positioner (ADR 0012): it inherits the popper positioning surface (inputs, `placed`
554
+ * output, unified vars + placement attrs) from {@link RdxPopperContentWrapper} and adds preview-card's
555
+ * own concerns — Base UI-aligned defaults via the config provider, the open/closed/instant state
556
+ * attributes, the deprecated `--radix-preview-card-*` aliases, and the grace-area hover bridge.
518
557
  */
519
- class RdxPreviewCardPositioner {
558
+ class RdxPreviewCardPositioner extends RdxPopperContentWrapper {
520
559
  constructor() {
560
+ super();
521
561
  this.rootContext = injectRdxPreviewCardRootContext();
522
- this.wrapper = inject(RdxPopperContentWrapper);
523
- this.elementRef = inject(ElementRef);
562
+ this.legacyVars = legacyPopperVars('preview-card');
563
+ this.containerRef = inject(ElementRef);
524
564
  this.triggerEl = signal(null, ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
525
- this.containerEl = signal(this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "containerEl" }] : /* istanbul ignore next */ []));
565
+ this.containerEl = signal(this.containerRef.nativeElement, ...(ngDevMode ? [{ debugName: "containerEl" }] : /* istanbul ignore next */ []));
526
566
  this.graceArea = useGraceArea(this.triggerEl, this.containerEl);
527
- /**
528
- * An element to position the popup against. Defaults to the trigger.
529
- */
530
- this.anchor = input(...(ngDevMode ? [undefined, { debugName: "anchor" }] : /* istanbul ignore next */ []));
531
- /**
532
- * The preferred side of the trigger to render against when open.
533
- */
534
- this.side = input('bottom', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
535
- /**
536
- * Distance between the trigger and the popup in pixels.
537
- */
538
- this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
539
- /**
540
- * How to align the popup relative to the specified side.
541
- */
542
- this.align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
543
- /**
544
- * An offset in pixels from the `start` or `end` alignment options.
545
- */
546
- this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
547
- /**
548
- * Minimum distance to maintain between the arrow and the edges of the popup.
549
- */
550
- this.arrowPadding = input(5, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
551
- /**
552
- * Whether to override side and alignment preferences to prevent collisions.
553
- */
554
- this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
555
- /**
556
- * The element used as the collision boundary.
557
- */
558
- this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
559
- /**
560
- * Distance in pixels from the boundary edges where collision detection should occur.
561
- */
562
- this.collisionPadding = input(5, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
563
- /**
564
- * The sticky behavior on the alignment axis.
565
- */
566
- this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
567
- /**
568
- * Whether to hide the popup when the trigger becomes fully occluded.
569
- */
570
- this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
571
- /**
572
- * The CSS position strategy used by Floating UI.
573
- */
574
- this.positionStrategy = input('fixed', ...(ngDevMode ? [{ debugName: "positionStrategy" }] : /* istanbul ignore next */ []));
575
- /**
576
- * Whether to update position on every animation frame.
577
- */
578
- this.updatePositionStrategy = input('always', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
579
- /**
580
- * Emits when the popup has been placed.
581
- */
582
- this.placed = outputFromObservable(outputToObservable(inject(RdxPopperContentWrapper).placed));
583
567
  effect(() => this.triggerEl.set(this.rootContext.trigger() ?? null));
584
568
  this.graceArea.onPointerExit(() => {
585
569
  this.rootContext.closeOnHover();
586
570
  });
587
571
  }
588
572
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
589
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxPreviewCardPositioner, isStandalone: true, selector: "[rdxPreviewCardPositioner]", 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-preview-card-content-transform-origin': 'var(--radix-popper-transform-origin)',\n '--radix-preview-card-content-available-width': 'var(--radix-popper-available-width)',\n '--radix-preview-card-content-available-height': 'var(--radix-popper-available-height)',\n '--radix-preview-card-trigger-width': 'var(--radix-popper-anchor-width)',\n '--radix-preview-card-trigger-height': 'var(--radix-popper-anchor-height)'\n }" } }, providers: [
573
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxPreviewCardPositioner, isStandalone: true, selector: "[rdxPreviewCardPositioner]", host: { properties: { "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"", "attr.data-instant": "rootContext.instant() ? \"\" : undefined", "style": "legacyVars" } }, providers: [
574
+ ...provideRdxPopperContentWrapper(RdxPreviewCardPositioner),
590
575
  provideRdxPopperContentConfig({ arrowPadding: 5, collisionPadding: 5, updatePositionStrategy: 'always' })
591
- ], 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 }); }
576
+ ], usesInheritance: true, ngImport: i0 }); }
592
577
  }
593
578
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardPositioner, decorators: [{
594
579
  type: Directive,
595
580
  args: [{
596
581
  selector: '[rdxPreviewCardPositioner]',
597
582
  providers: [
583
+ ...provideRdxPopperContentWrapper(RdxPreviewCardPositioner),
598
584
  provideRdxPopperContentConfig({ arrowPadding: 5, collisionPadding: 5, updatePositionStrategy: 'always' })
599
585
  ],
600
- hostDirectives: [
601
- {
602
- directive: RdxPopperContentWrapper,
603
- inputs: [
604
- 'anchor',
605
- 'side',
606
- 'sideOffset',
607
- 'align',
608
- 'alignOffset',
609
- 'arrowPadding',
610
- 'avoidCollisions',
611
- 'collisionBoundary',
612
- 'collisionPadding',
613
- 'sticky',
614
- 'hideWhenDetached',
615
- 'positionStrategy',
616
- 'updatePositionStrategy'
617
- ]
618
- }
619
- ],
620
586
  host: {
621
587
  '[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
622
588
  '[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""',
623
- '[attr.data-anchor-hidden]': 'wrapper.anchorHidden() ? "" : undefined',
624
- '[attr.data-align]': 'wrapper.placedAlign()',
625
- '[attr.data-side]': 'wrapper.placedSide()',
626
589
  '[attr.data-instant]': 'rootContext.instant() ? "" : undefined',
627
- '[style]': `{
628
- '--anchor-width': 'var(--radix-popper-anchor-width)',
629
- '--anchor-height': 'var(--radix-popper-anchor-height)',
630
- '--available-width': 'var(--radix-popper-available-width)',
631
- '--available-height': 'var(--radix-popper-available-height)',
632
- '--positioner-width': 'var(--radix-popper-content-wrapper-width)',
633
- '--positioner-height': 'var(--radix-popper-content-wrapper-height)',
634
- '--transform-origin': 'var(--radix-popper-transform-origin)',
635
- '--radix-preview-card-content-transform-origin': 'var(--radix-popper-transform-origin)',
636
- '--radix-preview-card-content-available-width': 'var(--radix-popper-available-width)',
637
- '--radix-preview-card-content-available-height': 'var(--radix-popper-available-height)',
638
- '--radix-preview-card-trigger-width': 'var(--radix-popper-anchor-width)',
639
- '--radix-preview-card-trigger-height': 'var(--radix-popper-anchor-height)'
640
- }`
590
+ // `data-side`/`data-align`/`data-anchor-hidden` and the unified `--anchor-*`/`--available-*`/
591
+ // `--transform-origin` vars come from the inherited wrapper (ADR 0012); only the deprecated
592
+ // `--radix-preview-card-*` aliases remain, for one release of back-compat.
593
+ '[style]': 'legacyVars'
641
594
  }
642
595
  }]
643
- }], 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"] }] } });
596
+ }], ctorParameters: () => [] });
644
597
 
645
598
  /**
646
599
  * A link or element that opens the preview card.
@@ -678,6 +631,7 @@ class RdxPreviewCardTrigger {
678
631
  this.isOpen = computed(() => this.rootContext()?.isOpen() === true && this.rootContext()?.trigger() === this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
679
632
  this.isPressed = computed(() => this.isOpen() && this.rootContext()?.openChangeReason() === 'trigger-press', ...(ngDevMode ? [{ debugName: "isPressed" }] : /* istanbul ignore next */ []));
680
633
  this.generatedId = injectId('rdx-preview-card-trigger-');
634
+ rdxCheckTriggerElement('rdxPreviewCardTrigger', 'preview-card/trigger-element', 'components/preview-card');
681
635
  effect((onCleanup) => {
682
636
  const handle = this.handle();
683
637
  if (handle) {
@@ -952,8 +906,8 @@ function createRdxPreviewCardHandle() {
952
906
  const previewCardImports = [
953
907
  RdxPreviewCardRoot,
954
908
  RdxPreviewCardTrigger,
955
- RdxPreviewCardPortalPresence,
956
909
  RdxPreviewCardPortal,
910
+ RdxPreviewCardPortalMisuseGuard,
957
911
  RdxPreviewCardBackdrop,
958
912
  RdxPreviewCardPositioner,
959
913
  RdxPreviewCardPopup,
@@ -964,16 +918,16 @@ class RdxPreviewCardModule {
964
918
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
965
919
  static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.9", ngImport: i0, type: RdxPreviewCardModule, imports: [RdxPreviewCardRoot,
966
920
  RdxPreviewCardTrigger,
967
- RdxPreviewCardPortalPresence,
968
921
  RdxPreviewCardPortal,
922
+ RdxPreviewCardPortalMisuseGuard,
969
923
  RdxPreviewCardBackdrop,
970
924
  RdxPreviewCardPositioner,
971
925
  RdxPreviewCardPopup,
972
926
  RdxPreviewCardArrow,
973
927
  RdxPreviewCardViewport], exports: [RdxPreviewCardRoot,
974
928
  RdxPreviewCardTrigger,
975
- RdxPreviewCardPortalPresence,
976
929
  RdxPreviewCardPortal,
930
+ RdxPreviewCardPortalMisuseGuard,
977
931
  RdxPreviewCardBackdrop,
978
932
  RdxPreviewCardPositioner,
979
933
  RdxPreviewCardPopup,
@@ -993,5 +947,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
993
947
  * Generated bundle index. Do not edit.
994
948
  */
995
949
 
996
- export { RdxPreviewCardArrow, RdxPreviewCardBackdrop, RdxPreviewCardHandle, RdxPreviewCardModule, RdxPreviewCardPopup, RdxPreviewCardPortal, RdxPreviewCardPortalPresence, RdxPreviewCardPositioner, RdxPreviewCardRoot, RdxPreviewCardTrigger, RdxPreviewCardViewport, createRdxPreviewCardHandle, injectRdxPreviewCardRootContext, previewCardImports, provideRdxPreviewCardRootContext };
950
+ export { RdxPreviewCardArrow, RdxPreviewCardBackdrop, RdxPreviewCardHandle, RdxPreviewCardModule, RdxPreviewCardPopup, RdxPreviewCardPortal, RdxPreviewCardPortalMisuseGuard, RdxPreviewCardPositioner, RdxPreviewCardRoot, RdxPreviewCardTrigger, RdxPreviewCardViewport, createRdxPreviewCardHandle, injectRdxPreviewCardRootContext, previewCardImports, provideRdxPreviewCardRootContext };
997
951
  //# sourceMappingURL=radix-ng-primitives-preview-card.mjs.map