@radix-ng/primitives 1.0.0-beta.3 → 1.0.0-beta.5

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 (118) hide show
  1. package/README.md +1 -1
  2. package/fesm2022/radix-ng-primitives-accordion.mjs +5 -3
  3. package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
  4. package/fesm2022/radix-ng-primitives-alert-dialog.mjs +3 -2
  5. package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
  6. package/fesm2022/radix-ng-primitives-autocomplete.mjs +617 -659
  7. package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
  8. package/fesm2022/radix-ng-primitives-calendar.mjs +5 -3
  9. package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
  10. package/fesm2022/radix-ng-primitives-checkbox.mjs +33 -18
  11. package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
  12. package/fesm2022/radix-ng-primitives-combobox.mjs +1305 -572
  13. package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
  14. package/fesm2022/radix-ng-primitives-config.mjs +13 -4
  15. package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
  16. package/fesm2022/radix-ng-primitives-context-menu.mjs +51 -10
  17. package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
  18. package/fesm2022/radix-ng-primitives-core.mjs +1352 -64
  19. package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
  20. package/fesm2022/radix-ng-primitives-date-field.mjs +5 -3
  21. package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
  22. package/fesm2022/radix-ng-primitives-dialog.mjs +290 -120
  23. package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
  24. package/fesm2022/radix-ng-primitives-direction-provider.mjs +70 -0
  25. package/fesm2022/radix-ng-primitives-direction-provider.mjs.map +1 -0
  26. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +519 -184
  27. package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
  28. package/fesm2022/radix-ng-primitives-drawer.mjs +3 -3
  29. package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
  30. package/fesm2022/radix-ng-primitives-editable.mjs +12 -7
  31. package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
  32. package/fesm2022/radix-ng-primitives-field.mjs +3 -2
  33. package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
  34. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +803 -0
  35. package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -0
  36. package/fesm2022/radix-ng-primitives-focus-scope.mjs +305 -70
  37. package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
  38. package/fesm2022/radix-ng-primitives-menu.mjs +893 -289
  39. package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
  40. package/fesm2022/radix-ng-primitives-menubar.mjs +32 -4
  41. package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
  42. package/fesm2022/radix-ng-primitives-navigation-menu.mjs +144 -159
  43. package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
  44. package/fesm2022/radix-ng-primitives-number-field.mjs +7 -2
  45. package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
  46. package/fesm2022/radix-ng-primitives-popover.mjs +284 -212
  47. package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
  48. package/fesm2022/radix-ng-primitives-popper.mjs +94 -51
  49. package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
  50. package/fesm2022/radix-ng-primitives-presence.mjs +1 -1
  51. package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
  52. package/fesm2022/radix-ng-primitives-preview-card.mjs +141 -173
  53. package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
  54. package/fesm2022/radix-ng-primitives-radio.mjs +19 -14
  55. package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
  56. package/fesm2022/radix-ng-primitives-roving-focus.mjs +4 -2
  57. package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
  58. package/fesm2022/radix-ng-primitives-scroll-area.mjs +5 -4
  59. package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
  60. package/fesm2022/radix-ng-primitives-select.mjs +241 -164
  61. package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
  62. package/fesm2022/radix-ng-primitives-slider.mjs +262 -29
  63. package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
  64. package/fesm2022/radix-ng-primitives-stepper.mjs +16 -10
  65. package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
  66. package/fesm2022/radix-ng-primitives-switch.mjs +10 -5
  67. package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
  68. package/fesm2022/radix-ng-primitives-tabs.mjs +15 -10
  69. package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
  70. package/fesm2022/radix-ng-primitives-time-field.mjs +5 -3
  71. package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
  72. package/fesm2022/radix-ng-primitives-toast.mjs +15 -36
  73. package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
  74. package/fesm2022/radix-ng-primitives-toggle-group.mjs +14 -7
  75. package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
  76. package/fesm2022/radix-ng-primitives-toggle.mjs +12 -6
  77. package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
  78. package/fesm2022/radix-ng-primitives-toolbar.mjs +5 -3
  79. package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
  80. package/fesm2022/radix-ng-primitives-tooltip.mjs +251 -143
  81. package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
  82. package/package.json +10 -1
  83. package/types/radix-ng-primitives-accordion.d.ts +4 -3
  84. package/types/radix-ng-primitives-autocomplete.d.ts +217 -152
  85. package/types/radix-ng-primitives-calendar.d.ts +5 -3
  86. package/types/radix-ng-primitives-checkbox.d.ts +27 -15
  87. package/types/radix-ng-primitives-combobox.d.ts +672 -283
  88. package/types/radix-ng-primitives-config.d.ts +1 -1
  89. package/types/radix-ng-primitives-context-menu.d.ts +15 -5
  90. package/types/radix-ng-primitives-core.d.ts +764 -14
  91. package/types/radix-ng-primitives-date-field.d.ts +3 -2
  92. package/types/radix-ng-primitives-dialog.d.ts +88 -32
  93. package/types/radix-ng-primitives-direction-provider.d.ts +41 -0
  94. package/types/radix-ng-primitives-dismissable-layer.d.ts +147 -99
  95. package/types/radix-ng-primitives-editable.d.ts +11 -5
  96. package/types/radix-ng-primitives-field.d.ts +1 -0
  97. package/types/radix-ng-primitives-floating-focus-manager.d.ts +272 -0
  98. package/types/radix-ng-primitives-focus-scope.d.ts +132 -1
  99. package/types/radix-ng-primitives-menu.d.ts +192 -103
  100. package/types/radix-ng-primitives-navigation-menu.d.ts +37 -75
  101. package/types/radix-ng-primitives-number-field.d.ts +8 -3
  102. package/types/radix-ng-primitives-popover.d.ts +71 -92
  103. package/types/radix-ng-primitives-popper.d.ts +39 -9
  104. package/types/radix-ng-primitives-preview-card.d.ts +39 -72
  105. package/types/radix-ng-primitives-radio.d.ts +13 -6
  106. package/types/radix-ng-primitives-roving-focus.d.ts +7 -6
  107. package/types/radix-ng-primitives-scroll-area.d.ts +2 -2
  108. package/types/radix-ng-primitives-select.d.ts +142 -109
  109. package/types/radix-ng-primitives-slider.d.ts +64 -12
  110. package/types/radix-ng-primitives-stepper.d.ts +15 -7
  111. package/types/radix-ng-primitives-switch.d.ts +10 -4
  112. package/types/radix-ng-primitives-tabs.d.ts +12 -6
  113. package/types/radix-ng-primitives-time-field.d.ts +3 -2
  114. package/types/radix-ng-primitives-toast.d.ts +7 -7
  115. package/types/radix-ng-primitives-toggle-group.d.ts +15 -8
  116. package/types/radix-ng-primitives-toggle.d.ts +10 -3
  117. package/types/radix-ng-primitives-toolbar.d.ts +3 -2
  118. package/types/radix-ng-primitives-tooltip.d.ts +61 -80
@@ -1,26 +1,527 @@
1
+ import { isPlatformBrowser } from '@angular/common';
1
2
  import * as i0 from '@angular/core';
2
- import { InjectionToken, signal, computed, input, booleanAttribute, linkedSignal, output, inject, ElementRef, effect, Directive, DestroyRef, afterNextRender, Injector, untracked } from '@angular/core';
3
+ import { inject, DestroyRef, PLATFORM_ID, ElementRef, Directive, input, booleanAttribute, linkedSignal, output, signal, effect, afterNextRender } from '@angular/core';
4
+ import { RDX_FLOATING_MARKER } from '@radix-ng/primitives/floating-focus-manager';
5
+ import { RDX_FLOATING_ROOT_CONTEXT } from '@radix-ng/primitives/core';
3
6
 
4
- const RdxDismissableLayersContextToken = new InjectionToken('RdxDismissableLayersContextToken', {
5
- factory() {
6
- const layersRoot = signal([], ...(ngDevMode ? [{ debugName: "layersRoot" }] : /* istanbul ignore next */ []));
7
- return {
8
- layersRoot,
9
- layersWithOutsidePointerEventsDisabled: computed(() => layersRoot().filter((i) => i.isOutsidePointerEventsDisabled())),
10
- branches: signal([])
11
- };
7
+ const alwaysTrue = () => true;
8
+ const alwaysFalse = () => false;
9
+ const sloppy = () => 'sloppy';
10
+ /** Duck-types an `EventTarget` to `Node` (cross-realm-safe; `Node.contains` throws on a non-Node). */
11
+ function isNode(target) {
12
+ return target !== null && typeof target.nodeType === 'number';
13
+ }
14
+ /**
15
+ * Owner-document-safe `HTMLElement` check. A raw `target instanceof HTMLElement` is realm-sensitive — it
16
+ * returns `false` for an element from another document (iframe / popup window) because that realm has its
17
+ * own `HTMLElement` constructor. Resolve the constructor from the node's own `defaultView` (Base UI
18
+ * `isHTMLElement`).
19
+ */
20
+ function isHTMLElement(target) {
21
+ if (!isNode(target)) {
22
+ return false;
23
+ }
24
+ const view = target.ownerDocument?.defaultView;
25
+ return view ? target instanceof view.HTMLElement : target instanceof HTMLElement;
26
+ }
27
+ /** Owner-document-safe `Element` check for SVG/custom-element outside targets. */
28
+ function isElement(target) {
29
+ if (!isNode(target)) {
30
+ return false;
31
+ }
32
+ const view = target.ownerDocument?.defaultView;
33
+ return view ? target instanceof view.Element : target instanceof Element;
34
+ }
35
+ /**
36
+ * Whether `window` is a WebKit (Safari / any iOS browser) engine — its IME `compositionend`/`keydown`
37
+ * ordering needs a longer guard. Requires the `Safari` token and excludes desktop Blink (Chrome /
38
+ * Edge / Android), so jsdom (`AppleWebKit/537.36 … jsdom`, no `Safari`) is correctly **not** WebKit and
39
+ * the unit timing stays 0ms.
40
+ */
41
+ function isWebKit(window) {
42
+ const ua = window.navigator.userAgent;
43
+ return /AppleWebKit/i.test(ua) && /Safari/i.test(ua) && !/Chrome|Chromium|Edg|Android/i.test(ua);
44
+ }
45
+ /** Only a primary (left / default) press dismisses — a non-primary mouse button is ignored. */
46
+ function isPrimaryButton(event) {
47
+ return !('button' in event) || event.button === 0;
48
+ }
49
+ function isRootElement(element) {
50
+ const document = element.ownerDocument;
51
+ return element === document.documentElement || element === document.body;
52
+ }
53
+ function isShadowRoot(value) {
54
+ return value !== null && value.nodeType === 11 && 'host' in value;
55
+ }
56
+ function getParentNode(element) {
57
+ const parent = element.parentNode;
58
+ if (parent) {
59
+ return parent;
60
+ }
61
+ const root = element.getRootNode();
62
+ return isShadowRoot(root) ? root.host : null;
63
+ }
64
+ function isLastTraversableNode(node) {
65
+ return (node === null ||
66
+ node.nodeType === Node.DOCUMENT_NODE ||
67
+ isShadowRoot(node) ||
68
+ (isElement(node) && isRootElement(node)));
69
+ }
70
+ function getTargetRootAncestor(target) {
71
+ let ancestor = target;
72
+ while (!isLastTraversableNode(ancestor)) {
73
+ const parent = getParentNode(ancestor);
74
+ if (isLastTraversableNode(parent) || !isElement(parent)) {
75
+ break;
76
+ }
77
+ ancestor = parent;
78
+ }
79
+ return ancestor;
80
+ }
81
+ /**
82
+ * Base UI third-party guard: ignore elements injected after `markOthers` ran. A normal outside target sits
83
+ * in a root subtree that contains at least one marker; an injected root does not.
84
+ */
85
+ function isInjectedAfterMark(target, context) {
86
+ if (!isElement(target) || isRootElement(target)) {
87
+ return false;
12
88
  }
13
- });
14
- const RdxDismissableLayerConfigToken = new InjectionToken('RdxDismissableLayerConfig', {
15
- factory: () => {
16
- return {
17
- disableOutsidePointerEvents: signal(false)
89
+ if (target.closest('[data-rdx-internal-backdrop], [data-rdx-menu-internal-backdrop], [data-rdx-dialog-internal-backdrop]')) {
90
+ return false;
91
+ }
92
+ const targetRoot = target.getRootNode();
93
+ const queryRoot = isShadowRoot(targetRoot) ? targetRoot : context.ownerDocument;
94
+ const markers = Array.from(queryRoot.querySelectorAll(`[${RDX_FLOATING_MARKER}]`));
95
+ if (markers.length === 0) {
96
+ return false;
97
+ }
98
+ const floating = context.floatingElement;
99
+ if (floating && target.contains(floating)) {
100
+ return false;
101
+ }
102
+ const targetRootAncestor = getTargetRootAncestor(target);
103
+ return markers.every((marker) => !targetRootAncestor.contains(marker));
104
+ }
105
+ /**
106
+ * Whether the press landed on `target`'s scrollbar (a scrollbar drag must not dismiss). Mirrors Base
107
+ * UI's geometry check (`useDismiss.ts`): skipped for touch (scrollbars get no touch events) and resolved
108
+ * from the element's scroll metrics + the press offset.
109
+ *
110
+ * @remarks Layout-dependent — verified by Playwright, not jsdom (which reports zero box metrics, so this
111
+ * correctly returns `false` there). See `apps/visual-regression`.
112
+ */
113
+ function isScrollbarPress(event) {
114
+ const target = event.target;
115
+ if (!isHTMLElement(target) || 'touches' in event || typeof event.offsetX !== 'number') {
116
+ return false;
117
+ }
118
+ const view = target.ownerDocument.defaultView;
119
+ if (!view) {
120
+ return false;
121
+ }
122
+ const press = event;
123
+ const style = view.getComputedStyle(target);
124
+ const scrollable = /auto|scroll/;
125
+ const lastTraversableNode = isLastTraversableNode(target);
126
+ const isScrollableX = lastTraversableNode || scrollable.test(style.overflowX);
127
+ const isScrollableY = lastTraversableNode || scrollable.test(style.overflowY);
128
+ const canScrollX = isScrollableX && target.clientWidth > 0 && target.scrollWidth > target.clientWidth;
129
+ const canScrollY = isScrollableY && target.clientHeight > 0 && target.scrollHeight > target.clientHeight;
130
+ const isRtl = style.direction === 'rtl';
131
+ const onVerticalScrollbar = canScrollY &&
132
+ (isRtl ? press.offsetX <= target.offsetWidth - target.clientWidth : press.offsetX > target.clientWidth);
133
+ const onHorizontalScrollbar = canScrollX && press.offsetY > target.clientHeight;
134
+ return onVerticalScrollbar || onHorizontalScrollbar;
135
+ }
136
+ /**
137
+ * Each capability publishes its bubbles policy here, keyed by its root context, so an **ancestor**'s
138
+ * `hasBlockingChild` can read a child's flags — the Angular counterpart of Base UI storing
139
+ * `__escapeKeyBubbles` / `__outsidePressBubbles` on the context's `dataRef` (`useDismiss.ts`). Kept in a
140
+ * dismissal-private `WeakMap` (not on the neutral context) so the context stays capability-agnostic.
141
+ */
142
+ const dismissBubblesByContext = new WeakMap();
143
+ /**
144
+ * Whether a child `context` lets the given event bubble past it to its ancestors. Defaults match Base
145
+ * UI for a child that has no dismissal policy (e.g. focus-only): Escape does **not** bubble (so it
146
+ * blocks), an outside press **does** (so it does not block).
147
+ */
148
+ function childBubbles(context, reason) {
149
+ const bubbles = dismissBubblesByContext.get(context);
150
+ if (reason === 'escape-key') {
151
+ return bubbles ? bubbles.escapeKey() : false;
152
+ }
153
+ return bubbles ? bubbles.outsidePress() : true;
154
+ }
155
+ /**
156
+ * The **dismiss** mechanism (ADR 0015) — the Angular counterpart of Base UI's `useDismiss`. It
157
+ * **references** a {@link RdxFloatingRootContext} (mandatory: `open` / `triggers` / elements live there)
158
+ * and a {@link RdxFloatingNode} (**optional**: a node-optional / Navigation-Menu state has `node ===
159
+ * null`); it never creates them. It listens for Escape / outside-press / focus-out and **requests** a
160
+ * dismissal via `onDismiss` when an interaction lands outside the logical layer and this layer owns the
161
+ * event.
162
+ *
163
+ * **Logical, not DOM-order, containment.** "Inside" is resolved through the shared tree — this popup's
164
+ * floating element + its registered triggers, **plus** the same for every open descendant node, **plus**
165
+ * this layer's own {@link branches}. So a portal-relocated child still counts as inside its parent — which
166
+ * a DOM-order containment check cannot do.
167
+ *
168
+ * **Ownership & propagation (`hasBlockingChild`).** Each layer publishes per-event `bubbles` flags
169
+ * (`escapeKeyBubbles` default `false`, `outsidePressBubbles` default `true`); an ancestor reads its open
170
+ * children's flags via {@link childBubbles}. A non-bubbling layer **yields** to a non-bubbling open child,
171
+ * so by default Escape closes only the **deepest** layer while an outside press closes the **whole stack**.
172
+ * A layer with `escapeKeyBubbles = true` re-emits to its parent (Menu's `closeParentOnEsc`). The owning
173
+ * non-bubbling Escape layer also `stopPropagation()`s so the key does not reach app handlers.
174
+ *
175
+ * **Press / IME hardening.** Outside-press honors `outsidePressEvent` (`'sloppy'` → `pointerdown`,
176
+ * `'intentional'` → `click` with press-start-inside drag-out suppression), ignores non-primary mouse
177
+ * buttons and scrollbar presses, resets on `pointercancel`, and ignores Escape while an IME composition is
178
+ * active. **Touch** sloppy-mode gesture hardening (long-press / drag-distance thresholds) is ported here
179
+ * but only unit-exercisable via synthetic events — real on-device behavior is covered by
180
+ * `apps/visual-regression` (Playwright).
181
+ *
182
+ * **Scope.** Must be constructed in an injection context (`DestroyRef` / `PLATFORM_ID`). No-op on the
183
+ * server.
184
+ */
185
+ class RdxDismiss {
186
+ constructor(context, node, config = {}) {
187
+ this.context = context;
188
+ this.node = node;
189
+ /** This layer's own inside-content set (branches that live outside the popup DOM). */
190
+ this.branches = new Set();
191
+ const enabled = config.enabled ?? alwaysTrue;
192
+ const escapeKey = config.escapeKey ?? alwaysTrue;
193
+ const escapeKeyBubbles = config.escapeKeyBubbles ?? alwaysFalse;
194
+ const outsidePress = config.outsidePress ?? alwaysTrue;
195
+ const outsidePressBubbles = config.outsidePressBubbles ?? alwaysTrue;
196
+ const outsidePressEvent = config.outsidePressEvent ?? sloppy;
197
+ const focusOutside = config.focusOutside ?? alwaysTrue;
198
+ // Plain function (not `computed`) so it re-reads `open()` per event even when `open` is not a
199
+ // signal — while still tracking signals when read inside a reactive context.
200
+ this.active = () => this.context.open() && enabled();
201
+ // Publish this layer's bubbles policy so an ANCESTOR's hasBlockingChild can read it. Registered
202
+ // (and cleaned up) regardless of platform so SSR leaves no stale entry.
203
+ dismissBubblesByContext.set(this.context, { escapeKey: escapeKeyBubbles, outsidePress: outsidePressBubbles });
204
+ const destroyRef = inject(DestroyRef);
205
+ destroyRef.onDestroy(() => dismissBubblesByContext.delete(this.context));
206
+ if (!isPlatformBrowser(inject(PLATFORM_ID))) {
207
+ return; // SSR: no listeners, no DOM access.
208
+ }
209
+ const ownerDocument = this.context.ownerDocument;
210
+ const ownerWindow = ownerDocument.defaultView ?? globalThis;
211
+ const dismiss = (reason, event) => {
212
+ config.onDismiss?.(reason, event);
213
+ };
214
+ // IME: a press of Escape while composing should close the compose menu, not the popup.
215
+ let isComposing = false;
216
+ // Press-start-inside tracking (drag-out suppression for `intentional` mode).
217
+ let pressStartedInside = false;
218
+ // Pointer type of the active press, used to resolve a per-pointer-type `outsidePressEvent` map.
219
+ let currentPointerType = '';
220
+ // Touch outside-press hardening (Base UI `useDismiss`). For touch, a `sloppy` outside-press is
221
+ // NOT decided on the initial `pointerdown` (that would dismiss the moment a finger lands, even on
222
+ // the start of a scroll): a small drag (>5px) arms a close on `touchend`, a larger one (>10px)
223
+ // closes immediately (the user is scrolling away), and a plain tap closes via the synthetic
224
+ // `mousedown` that follows — unless the finger is held past a 1s grace window (a long-press).
225
+ let touchState = null;
226
+ let touchGraceTimer;
227
+ let touchClearTimer;
228
+ const clearTouchTimers = () => {
229
+ ownerWindow.clearTimeout(touchGraceTimer);
230
+ ownerWindow.clearTimeout(touchClearTimer);
18
231
  };
232
+ // Resolve `outsidePressEvent` to a concrete mode for the active pointer type (pen / unknown → mouse).
233
+ const resolveOutsidePressEvent = () => {
234
+ const value = outsidePressEvent();
235
+ if (typeof value === 'string') {
236
+ return value;
237
+ }
238
+ const type = currentPointerType === 'pen' || currentPointerType === '' ? 'mouse' : currentPointerType;
239
+ return value[type] ?? 'sloppy';
240
+ };
241
+ const handleKeyDown = (event) => {
242
+ if (event.key !== 'Escape' || !this.active() || !escapeKey() || isComposing) {
243
+ return;
244
+ }
245
+ // A non-bubbling layer yields to a deeper non-bubbling open layer (Base UI:
246
+ // `!escapeKeyBubbles && hasBlockingChild`). A bubbling layer never yields.
247
+ if (!escapeKeyBubbles() && this.hasBlockingChild('escape-key')) {
248
+ return;
249
+ }
250
+ config.onEscapeKeyDown?.(event);
251
+ if (!event.defaultPrevented) {
252
+ dismiss('escape-key', event);
253
+ }
254
+ // Propagation control: the owning non-bubbling layer consumes the Escape so it does not
255
+ // reach ancestor layers / app-level handlers (Base UI `event.stopPropagation()`).
256
+ if (!escapeKeyBubbles()) {
257
+ event.stopPropagation();
258
+ }
259
+ };
260
+ const handleCompositionStart = () => {
261
+ isComposing = true;
262
+ };
263
+ const handleCompositionEnd = () => {
264
+ // Safari fires `compositionend` before `keydown`, so clear on a later tick. 0ms/1ms are
265
+ // unreliable in Safari — WebKit needs ~5ms; other engines stay at 0ms (Base UI `useDismiss`).
266
+ ownerWindow.setTimeout(() => {
267
+ isComposing = false;
268
+ }, isWebKit(ownerWindow) ? 5 : 0);
269
+ };
270
+ const tryOutsidePress = (event) => {
271
+ if (!this.active() || !isPrimaryButton(event) || this.isInside(event.target) || !outsidePress(event)) {
272
+ return;
273
+ }
274
+ if (isInjectedAfterMark(event.target, this.context)) {
275
+ return;
276
+ }
277
+ if (isScrollbarPress(event)) {
278
+ return; // a scrollbar drag is not an outside press
279
+ }
280
+ // By default outside-press bubbles (closes the whole stack); only a non-bubbling layer with
281
+ // a non-bubbling open child yields to it.
282
+ if (!outsidePressBubbles() && this.hasBlockingChild('outside-press')) {
283
+ return;
284
+ }
285
+ config.onPointerDownOutside?.(event);
286
+ if (!event.defaultPrevented) {
287
+ dismiss('outside-press', event);
288
+ }
289
+ };
290
+ // Capture-phase, so it records where the press began (and its pointer type) before any dismiss
291
+ // handler runs.
292
+ const handlePressStart = (event) => {
293
+ pressStartedInside = this.isInside(event.target);
294
+ currentPointerType = event.pointerType || '';
295
+ };
296
+ const handlePointerCancel = () => {
297
+ pressStartedInside = false;
298
+ };
299
+ const handlePointerDown = (event) => {
300
+ if (resolveOutsidePressEvent() !== 'sloppy') {
301
+ return; // `intentional` dismisses on click, not pointerdown
302
+ }
303
+ if (event.pointerType === 'touch') {
304
+ return; // touch is decided by the touchstart/move/end + synthetic-mousedown machine below
305
+ }
306
+ tryOutsidePress(event);
307
+ };
308
+ const handleClick = (event) => {
309
+ if (resolveOutsidePressEvent() !== 'intentional') {
310
+ return;
311
+ }
312
+ // A press that started inside (text selection dragged out) consumes its one outside click.
313
+ if (pressStartedInside) {
314
+ pressStartedInside = false;
315
+ return;
316
+ }
317
+ tryOutsidePress(event);
318
+ };
319
+ // ─── Touch sloppy-mode hardening (Base UI `useDismiss`) ───────────────────
320
+ const handleTouchStart = (event) => {
321
+ currentPointerType = 'touch'; // a touch's pointer type, independent of pointerdown ordering
322
+ if (resolveOutsidePressEvent() !== 'sloppy' || !this.active() || this.isInside(event.target)) {
323
+ return;
324
+ }
325
+ const touch = event.touches?.[0];
326
+ if (!touch) {
327
+ return;
328
+ }
329
+ clearTouchTimers();
330
+ touchState = {
331
+ startX: touch.clientX,
332
+ startY: touch.clientY,
333
+ dismissOnTouchEnd: false,
334
+ dismissOnMouseDown: true
335
+ };
336
+ // After 1s the press is a long-press, not a dismissal — disarm both the touchend and the
337
+ // synthetic-mousedown close.
338
+ touchGraceTimer = ownerWindow.setTimeout(() => {
339
+ if (touchState) {
340
+ touchState.dismissOnTouchEnd = false;
341
+ touchState.dismissOnMouseDown = false;
342
+ }
343
+ }, 1000);
344
+ };
345
+ const handleTouchMove = (event) => {
346
+ if (!touchState || resolveOutsidePressEvent() !== 'sloppy' || this.isInside(event.target)) {
347
+ return;
348
+ }
349
+ const touch = event.touches?.[0];
350
+ if (!touch) {
351
+ return;
352
+ }
353
+ const dx = touch.clientX - touchState.startX;
354
+ const dy = touch.clientY - touchState.startY;
355
+ const distance = Math.sqrt(dx * dx + dy * dy);
356
+ if (distance > 5) {
357
+ touchState.dismissOnTouchEnd = true; // a deliberate drag — close when the finger lifts
358
+ }
359
+ if (distance > 10) {
360
+ tryOutsidePress(event); // scrolling away — close now
361
+ clearTouchTimers();
362
+ touchState = null;
363
+ }
364
+ };
365
+ const handleTouchEnd = (event) => {
366
+ if (!touchState || resolveOutsidePressEvent() !== 'sloppy' || this.isInside(event.target)) {
367
+ return;
368
+ }
369
+ if (touchState.dismissOnTouchEnd) {
370
+ tryOutsidePress(event);
371
+ clearTouchTimers();
372
+ touchState = null;
373
+ return;
374
+ }
375
+ // A plain tap: defer to the synthetic `mousedown` (which also lets us absorb the click-through),
376
+ // but drop the state shortly after in case no mouse event follows on this platform.
377
+ ownerWindow.clearTimeout(touchClearTimer);
378
+ touchClearTimer = ownerWindow.setTimeout(() => {
379
+ touchState = null;
380
+ }, 400);
381
+ };
382
+ const handleMouseDown = (event) => {
383
+ // Only the synthetic `mousedown` that follows a touch is handled here — a real mouse leaves
384
+ // `touchState` null and is dismissed by `handlePointerDown` instead (no double-close).
385
+ if (!touchState || resolveOutsidePressEvent() !== 'sloppy') {
386
+ return;
387
+ }
388
+ if (!touchState.dismissOnMouseDown) {
389
+ touchState = null; // grace expired (long-press) — do not dismiss
390
+ clearTouchTimers();
391
+ return;
392
+ }
393
+ tryOutsidePress(event);
394
+ clearTouchTimers();
395
+ touchState = null;
396
+ };
397
+ const handleFocusIn = (event) => {
398
+ // Defer two microtasks so focus settles before reading containment (matches the standalone
399
+ // RdxFocusOutside; the `on*` hook still runs synchronously, so `preventDefault` is honored).
400
+ void Promise.resolve()
401
+ .then(() => Promise.resolve())
402
+ .then(() => {
403
+ if (!this.active() || !focusOutside() || this.isInside(event.target)) {
404
+ return;
405
+ }
406
+ config.onFocusOutside?.(event);
407
+ if (!event.defaultPrevented) {
408
+ dismiss('focus-outside', event);
409
+ }
410
+ });
411
+ };
412
+ ownerDocument.addEventListener('keydown', handleKeyDown, { capture: true });
413
+ ownerDocument.addEventListener('compositionstart', handleCompositionStart, { capture: true });
414
+ ownerDocument.addEventListener('compositionend', handleCompositionEnd, { capture: true });
415
+ ownerDocument.addEventListener('focusin', handleFocusIn);
416
+ ownerDocument.addEventListener('pointerdown', handlePressStart, { capture: true });
417
+ ownerDocument.addEventListener('pointercancel', handlePointerCancel, { capture: true });
418
+ // Defer attaching the dismiss listeners past the current event loop so the very interaction that
419
+ // opened this layer doesn't immediately dismiss it (the opening press is still propagating).
420
+ const pointerTimer = ownerWindow.setTimeout(() => {
421
+ ownerDocument.addEventListener('pointerdown', handlePointerDown);
422
+ ownerDocument.addEventListener('click', handleClick);
423
+ ownerDocument.addEventListener('touchstart', handleTouchStart, { capture: true, passive: true });
424
+ ownerDocument.addEventListener('touchmove', handleTouchMove, { capture: true, passive: true });
425
+ ownerDocument.addEventListener('touchend', handleTouchEnd, { capture: true, passive: true });
426
+ ownerDocument.addEventListener('mousedown', handleMouseDown, { capture: true });
427
+ }, 0);
428
+ destroyRef.onDestroy(() => {
429
+ ownerWindow.clearTimeout(pointerTimer);
430
+ ownerDocument.removeEventListener('keydown', handleKeyDown, { capture: true });
431
+ ownerDocument.removeEventListener('compositionstart', handleCompositionStart, { capture: true });
432
+ ownerDocument.removeEventListener('compositionend', handleCompositionEnd, { capture: true });
433
+ ownerDocument.removeEventListener('focusin', handleFocusIn);
434
+ ownerDocument.removeEventListener('pointerdown', handlePressStart, { capture: true });
435
+ ownerDocument.removeEventListener('pointercancel', handlePointerCancel, { capture: true });
436
+ ownerDocument.removeEventListener('pointerdown', handlePointerDown);
437
+ ownerDocument.removeEventListener('click', handleClick);
438
+ ownerDocument.removeEventListener('touchstart', handleTouchStart, { capture: true });
439
+ ownerDocument.removeEventListener('touchmove', handleTouchMove, { capture: true });
440
+ ownerDocument.removeEventListener('touchend', handleTouchEnd, { capture: true });
441
+ ownerDocument.removeEventListener('mousedown', handleMouseDown, { capture: true });
442
+ clearTouchTimers();
443
+ });
19
444
  }
20
- });
21
- function provideRdxDismissableLayerConfig(factory) {
22
- return { provide: RdxDismissableLayerConfigToken, useFactory: factory };
445
+ /**
446
+ * Whether `target` is logically inside this layer: within this popup's floating element or one of its
447
+ * registered triggers, within any **open descendant** node's floating element / triggers, or within a
448
+ * registered branch.
449
+ */
450
+ isInside(target) {
451
+ if (this.contextContains(this.context, target)) {
452
+ return true;
453
+ }
454
+ const node = this.node();
455
+ if (node) {
456
+ for (const child of node.tree.children(node, { onlyOpen: true })) {
457
+ if (child.context && this.contextContains(child.context, target)) {
458
+ return true;
459
+ }
460
+ }
461
+ }
462
+ if (isNode(target)) {
463
+ for (const branch of this.branches) {
464
+ if (branch.contains(target)) {
465
+ return true;
466
+ }
467
+ }
468
+ }
469
+ return false;
470
+ }
471
+ /** `target` is inside a context's floating element or one of its registered triggers. */
472
+ contextContains(context, target) {
473
+ const floating = context.floatingElement;
474
+ if (floating && isNode(target) && floating.contains(target)) {
475
+ return true;
476
+ }
477
+ return context.triggers.contains(target);
478
+ }
479
+ /**
480
+ * Whether an open descendant blocks this layer for `reason` (so it should yield). A child blocks when
481
+ * it does **not** let the event bubble past it ({@link childBubbles} is `false`). Base UI's
482
+ * `hasBlockingChild` (`useDismiss.ts:170`) is a capability-local function — **not** a tree method — so
483
+ * the tree stays neutral.
484
+ */
485
+ hasBlockingChild(reason) {
486
+ const node = this.node();
487
+ if (!node) {
488
+ return false;
489
+ }
490
+ return node.tree
491
+ .children(node, { onlyOpen: true })
492
+ .some((child) => child.context !== null && !childBubbles(child.context, reason));
493
+ }
494
+ }
495
+
496
+ /**
497
+ * Marks its host as **inside** the enclosing floating layer (ADR 0015): a pointer / focus interaction on
498
+ * it does not count as "outside", so it never dismisses the popup. It registers the host into the
499
+ * floating root context's trigger registry — {@link RdxDismiss}'s `isInside` check reads it.
500
+ *
501
+ * Use it for an element that lives **outside** the popup DOM but logically belongs to the layer — e.g. a
502
+ * Combobox input / trigger / chips / clear button that keeps focus (or is clicked) while the listbox is
503
+ * open.
504
+ */
505
+ class RdxFloatingInsideElement {
506
+ constructor() {
507
+ const context = inject(RDX_FLOATING_ROOT_CONTEXT, { optional: true });
508
+ if (!context) {
509
+ return;
510
+ }
511
+ const host = inject(ElementRef).nativeElement;
512
+ context.triggers.add(host);
513
+ inject(DestroyRef).onDestroy(() => context.triggers.delete(host));
514
+ }
515
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxFloatingInsideElement, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
516
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxFloatingInsideElement, isStandalone: true, selector: "[rdxFloatingInside]", exportAs: ["rdxFloatingInside"], ngImport: i0 }); }
23
517
  }
518
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxFloatingInsideElement, decorators: [{
519
+ type: Directive,
520
+ args: [{
521
+ selector: '[rdxFloatingInside]',
522
+ exportAs: 'rdxFloatingInside'
523
+ }]
524
+ }], ctorParameters: () => [] });
24
525
 
25
526
  function isLayerExist(layerElement, targetElement) {
26
527
  const targetLayer = targetElement.closest('[data-dismissable-layer]');
@@ -266,175 +767,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
266
767
  }]
267
768
  }], ctorParameters: () => [], propDecorators: { escapeKeyDown: [{ type: i0.Output, args: ["escapeKeyDown"] }] } });
268
769
 
269
- /**
270
- * Shared across all layers. Holds the body's original `pointer-events` value while at least one
271
- * layer disables outside pointer events. `null` means the body is not currently overridden — it
272
- * doubles as the "ownership" flag so stacked layers don't overwrite the saved original with
273
- * `none`.
274
- */
275
- let originalBodyPointerEvents = null;
276
- class RdxDismissableLayer {
277
- constructor() {
278
- this.elementRef = inject(ElementRef);
279
- this.injector = inject(Injector);
280
- this.destroyRef = inject(DestroyRef);
281
- this.context = inject(RdxDismissableLayersContextToken);
282
- this.config = inject(RdxDismissableLayerConfigToken);
283
- this.rdxPointerDownOutside = inject(RdxPointerDownOutside);
284
- this.rdxFocusOutside = inject(RdxFocusOutside);
285
- this.rdxEscapeKeyDown = inject(RdxEscapeKeyDown);
286
- /**
287
- * Event handler called when the escape key is down.
288
- * Can be prevented.
289
- */
290
- this.escapeKeyDown = output();
291
- /**
292
- * Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.
293
- * Can be prevented.
294
- */
295
- this.pointerDownOutside = output();
296
- /**
297
- * Event handler called when the focus moves outside of the `DismissableLayer`.
298
- * Can be prevented.
299
- */
300
- this.focusOutside = output();
301
- /**
302
- * Event handler called when an interaction happens outside the `DismissableLayer`.
303
- * Specifically, when a `pointerdown` event happens outside or focus moves outside of it.
304
- * Can be prevented.
305
- */
306
- this.interactOutside = output();
307
- /**
308
- * Handler called when the `DismissableLayer` should be dismissed
309
- */
310
- this.dismiss = output();
311
- /**
312
- * When `true`, hover/focus/click interactions will be disabled on elements outside
313
- * the `DismissableLayer`. Users will need to click twice on outside elements to
314
- * interact with them: once to close the `DismissableLayer`, and again to trigger the element.
315
- */
316
- this.disableOutsidePointerEvents = input(undefined, { ...(ngDevMode ? { debugName: "disableOutsidePointerEvents" } : /* istanbul ignore next */ {}), transform: (value) => (value === undefined ? undefined : booleanAttribute(value)) });
317
- this.isOutsidePointerEventsDisabled = computed(() => this.disableOutsidePointerEvents() ?? this.config.disableOutsidePointerEvents(), ...(ngDevMode ? [{ debugName: "isOutsidePointerEventsDisabled" }] : /* istanbul ignore next */ []));
318
- this.isBodyPointerEventsDisabled = computed(() => this.context.layersWithOutsidePointerEventsDisabled().length > 0, ...(ngDevMode ? [{ debugName: "isBodyPointerEventsDisabled" }] : /* istanbul ignore next */ []));
319
- this.isPointerEventsEnabled = computed(() => {
320
- const layers = this.context.layersRoot();
321
- const disabledLayers = this.context.layersWithOutsidePointerEventsDisabled();
322
- const highestDisabledLayer = disabledLayers[disabledLayers.length - 1];
323
- return this.index() >= layers.indexOf(highestDisabledLayer);
324
- }, ...(ngDevMode ? [{ debugName: "isPointerEventsEnabled" }] : /* istanbul ignore next */ []));
325
- this.index = computed(() => this.context.layersRoot().indexOf(this), ...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
326
- /** The topmost layer in the stack — the only one that should react to the Escape key. */
327
- this.isHighestLayer = computed(() => {
328
- const layers = this.context.layersRoot();
329
- return layers.indexOf(this) === layers.length - 1;
330
- }, ...(ngDevMode ? [{ debugName: "isHighestLayer" }] : /* istanbul ignore next */ []));
331
- this.context.layersRoot.update((v) => [...v, this]);
332
- this.destroyRef.onDestroy(() => {
333
- this.context.layersRoot.update((v) => v.filter((i) => i !== this));
334
- });
335
- this.setupBodyPointerEvents();
336
- this.rdxPointerDownOutside.pointerDownOutside.subscribe((event) => {
337
- const isPointerDownOnBranch = this.context
338
- .branches()
339
- .some((branch) => branch.contains(event.target));
340
- if (!this.isPointerEventsEnabled() || isPointerDownOnBranch) {
341
- return;
342
- }
343
- this.pointerDownOutside.emit(event);
344
- this.interactOutside.emit(event);
345
- if (!event.defaultPrevented) {
346
- this.dismiss.emit();
347
- }
348
- });
349
- this.rdxFocusOutside.focusOutside.subscribe((event) => {
350
- const isFocusInBranch = this.context
351
- .branches()
352
- .some((branch) => branch.contains(event.target));
353
- if (isFocusInBranch) {
354
- return;
355
- }
356
- this.focusOutside.emit(event);
357
- this.interactOutside.emit(event);
358
- if (!event.defaultPrevented) {
359
- this.dismiss.emit();
360
- }
361
- });
362
- this.rdxEscapeKeyDown.escapeKeyDown.subscribe((event) => {
363
- // Only the topmost layer is dismissed by Escape; stacked layers close one at a time.
364
- if (!this.isHighestLayer()) {
365
- return;
366
- }
367
- this.escapeKeyDown.emit(event);
368
- if (!event.defaultPrevented) {
369
- event.preventDefault();
370
- this.dismiss.emit();
371
- }
372
- });
373
- }
374
- /**
375
- * Toggles `pointer-events: none` on the document body while any layer has
376
- * `disableOutsidePointerEvents`. Ownership is shared across all layers via
377
- * {@link originalBodyPointerEvents}: the original value is saved only on the global
378
- * `0 -> >0` transition and restored only when the count returns to `0`.
379
- */
380
- setupBodyPointerEvents() {
381
- afterNextRender(() => {
382
- const ownerDocument = this.elementRef.nativeElement.ownerDocument ?? globalThis.document;
383
- effect((onCleanup) => {
384
- const disabledCount = this.context.layersWithOutsidePointerEventsDisabled().length;
385
- if (disabledCount > 0 && originalBodyPointerEvents === null) {
386
- originalBodyPointerEvents = ownerDocument.body.style.pointerEvents;
387
- ownerDocument.body.style.pointerEvents = 'none';
388
- }
389
- onCleanup(() => {
390
- const remaining = untracked(() => this.context.layersWithOutsidePointerEventsDisabled().length);
391
- if (remaining === 0 && originalBodyPointerEvents !== null) {
392
- ownerDocument.body.style.pointerEvents = originalBodyPointerEvents;
393
- originalBodyPointerEvents = null;
394
- }
395
- });
396
- }, { injector: this.injector });
397
- });
398
- }
399
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxDismissableLayer, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
400
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxDismissableLayer, isStandalone: true, selector: "[rdxDismissableLayer]", inputs: { disableOutsidePointerEvents: { classPropertyName: "disableOutsidePointerEvents", publicName: "disableOutsidePointerEvents", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside", focusOutside: "focusOutside", interactOutside: "interactOutside", dismiss: "dismiss" }, host: { attributes: { "data-dismissable-layer": "" }, properties: { "style": "{\n pointerEvents: isBodyPointerEventsDisabled() ? (isPointerEventsEnabled() ? 'auto' : 'none') : undefined\n }" } }, exportAs: ["rdxDismissableLayer"], hostDirectives: [{ directive: RdxPointerDownOutside }, { directive: RdxFocusOutside }, { directive: RdxEscapeKeyDown }], ngImport: i0 }); }
401
- }
402
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxDismissableLayer, decorators: [{
403
- type: Directive,
404
- args: [{
405
- selector: '[rdxDismissableLayer]',
406
- exportAs: 'rdxDismissableLayer',
407
- hostDirectives: [RdxPointerDownOutside, RdxFocusOutside, RdxEscapeKeyDown],
408
- host: {
409
- 'data-dismissable-layer': '',
410
- '[style]': `{
411
- pointerEvents: isBodyPointerEventsDisabled() ? (isPointerEventsEnabled() ? 'auto' : 'none') : undefined
412
- }`
413
- }
414
- }]
415
- }], 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"] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }], disableOutsidePointerEvents: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableOutsidePointerEvents", required: false }] }] } });
416
-
417
- class RdxDismissableLayerBranch {
418
- constructor() {
419
- this.elementRef = inject(ElementRef);
420
- this.destroyRef = inject(DestroyRef);
421
- this.dismissableLayersContext = inject(RdxDismissableLayersContextToken);
422
- this.dismissableLayersContext.branches.update((elements) => [...elements, this.elementRef.nativeElement]);
423
- this.destroyRef.onDestroy(() => this.dismissableLayersContext.branches.update((elements) => elements.filter((el) => el !== this.elementRef.nativeElement)));
424
- }
425
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxDismissableLayerBranch, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
426
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxDismissableLayerBranch, isStandalone: true, selector: "[rdxDismissableLayerBranch]", ngImport: i0 }); }
427
- }
428
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxDismissableLayerBranch, decorators: [{
429
- type: Directive,
430
- args: [{
431
- selector: '[rdxDismissableLayerBranch]'
432
- }]
433
- }], ctorParameters: () => [] });
434
-
435
770
  /**
436
771
  * Generated bundle index. Do not edit.
437
772
  */
438
773
 
439
- export { RdxDismissableLayer, RdxDismissableLayerBranch, RdxDismissableLayerConfigToken, RdxDismissableLayersContextToken, RdxEscapeKeyDown, RdxFocusOutside, RdxPointerDownOutside, provideRdxDismissableLayerConfig };
774
+ export { RdxDismiss, RdxEscapeKeyDown, RdxFloatingInsideElement, RdxFocusOutside, RdxPointerDownOutside };
440
775
  //# sourceMappingURL=radix-ng-primitives-dismissable-layer.mjs.map