@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.
- package/README.md +1 -1
- package/fesm2022/radix-ng-primitives-accordion.mjs +5 -3
- package/fesm2022/radix-ng-primitives-accordion.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-alert-dialog.mjs +3 -2
- package/fesm2022/radix-ng-primitives-alert-dialog.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-autocomplete.mjs +617 -659
- package/fesm2022/radix-ng-primitives-autocomplete.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-calendar.mjs +5 -3
- package/fesm2022/radix-ng-primitives-calendar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-checkbox.mjs +33 -18
- package/fesm2022/radix-ng-primitives-checkbox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-combobox.mjs +1305 -572
- package/fesm2022/radix-ng-primitives-combobox.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-config.mjs +13 -4
- package/fesm2022/radix-ng-primitives-config.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-context-menu.mjs +51 -10
- package/fesm2022/radix-ng-primitives-context-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-core.mjs +1352 -64
- package/fesm2022/radix-ng-primitives-core.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-date-field.mjs +5 -3
- package/fesm2022/radix-ng-primitives-date-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-dialog.mjs +290 -120
- package/fesm2022/radix-ng-primitives-dialog.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-direction-provider.mjs +70 -0
- package/fesm2022/radix-ng-primitives-direction-provider.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-dismissable-layer.mjs +519 -184
- package/fesm2022/radix-ng-primitives-dismissable-layer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-drawer.mjs +3 -3
- package/fesm2022/radix-ng-primitives-drawer.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-editable.mjs +12 -7
- package/fesm2022/radix-ng-primitives-editable.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-field.mjs +3 -2
- package/fesm2022/radix-ng-primitives-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs +803 -0
- package/fesm2022/radix-ng-primitives-floating-focus-manager.mjs.map +1 -0
- package/fesm2022/radix-ng-primitives-focus-scope.mjs +305 -70
- package/fesm2022/radix-ng-primitives-focus-scope.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menu.mjs +893 -289
- package/fesm2022/radix-ng-primitives-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-menubar.mjs +32 -4
- package/fesm2022/radix-ng-primitives-menubar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs +144 -159
- package/fesm2022/radix-ng-primitives-navigation-menu.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-number-field.mjs +7 -2
- package/fesm2022/radix-ng-primitives-number-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popover.mjs +284 -212
- package/fesm2022/radix-ng-primitives-popover.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-popper.mjs +94 -51
- package/fesm2022/radix-ng-primitives-popper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-presence.mjs +1 -1
- package/fesm2022/radix-ng-primitives-presence.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-preview-card.mjs +141 -173
- package/fesm2022/radix-ng-primitives-preview-card.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-radio.mjs +19 -14
- package/fesm2022/radix-ng-primitives-radio.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-roving-focus.mjs +4 -2
- package/fesm2022/radix-ng-primitives-roving-focus.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-scroll-area.mjs +5 -4
- package/fesm2022/radix-ng-primitives-scroll-area.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-select.mjs +241 -164
- package/fesm2022/radix-ng-primitives-select.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-slider.mjs +262 -29
- package/fesm2022/radix-ng-primitives-slider.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-stepper.mjs +16 -10
- package/fesm2022/radix-ng-primitives-stepper.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-switch.mjs +10 -5
- package/fesm2022/radix-ng-primitives-switch.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tabs.mjs +15 -10
- package/fesm2022/radix-ng-primitives-tabs.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-time-field.mjs +5 -3
- package/fesm2022/radix-ng-primitives-time-field.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toast.mjs +15 -36
- package/fesm2022/radix-ng-primitives-toast.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle-group.mjs +14 -7
- package/fesm2022/radix-ng-primitives-toggle-group.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toggle.mjs +12 -6
- package/fesm2022/radix-ng-primitives-toggle.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-toolbar.mjs +5 -3
- package/fesm2022/radix-ng-primitives-toolbar.mjs.map +1 -1
- package/fesm2022/radix-ng-primitives-tooltip.mjs +251 -143
- package/fesm2022/radix-ng-primitives-tooltip.mjs.map +1 -1
- package/package.json +10 -1
- package/types/radix-ng-primitives-accordion.d.ts +4 -3
- package/types/radix-ng-primitives-autocomplete.d.ts +217 -152
- package/types/radix-ng-primitives-calendar.d.ts +5 -3
- package/types/radix-ng-primitives-checkbox.d.ts +27 -15
- package/types/radix-ng-primitives-combobox.d.ts +672 -283
- package/types/radix-ng-primitives-config.d.ts +1 -1
- package/types/radix-ng-primitives-context-menu.d.ts +15 -5
- package/types/radix-ng-primitives-core.d.ts +764 -14
- package/types/radix-ng-primitives-date-field.d.ts +3 -2
- package/types/radix-ng-primitives-dialog.d.ts +88 -32
- package/types/radix-ng-primitives-direction-provider.d.ts +41 -0
- package/types/radix-ng-primitives-dismissable-layer.d.ts +147 -99
- package/types/radix-ng-primitives-editable.d.ts +11 -5
- package/types/radix-ng-primitives-field.d.ts +1 -0
- package/types/radix-ng-primitives-floating-focus-manager.d.ts +272 -0
- package/types/radix-ng-primitives-focus-scope.d.ts +132 -1
- package/types/radix-ng-primitives-menu.d.ts +192 -103
- package/types/radix-ng-primitives-navigation-menu.d.ts +37 -75
- package/types/radix-ng-primitives-number-field.d.ts +8 -3
- package/types/radix-ng-primitives-popover.d.ts +71 -92
- package/types/radix-ng-primitives-popper.d.ts +39 -9
- package/types/radix-ng-primitives-preview-card.d.ts +39 -72
- package/types/radix-ng-primitives-radio.d.ts +13 -6
- package/types/radix-ng-primitives-roving-focus.d.ts +7 -6
- package/types/radix-ng-primitives-scroll-area.d.ts +2 -2
- package/types/radix-ng-primitives-select.d.ts +142 -109
- package/types/radix-ng-primitives-slider.d.ts +64 -12
- package/types/radix-ng-primitives-stepper.d.ts +15 -7
- package/types/radix-ng-primitives-switch.d.ts +10 -4
- package/types/radix-ng-primitives-tabs.d.ts +12 -6
- package/types/radix-ng-primitives-time-field.d.ts +3 -2
- package/types/radix-ng-primitives-toast.d.ts +7 -7
- package/types/radix-ng-primitives-toggle-group.d.ts +15 -8
- package/types/radix-ng-primitives-toggle.d.ts +10 -3
- package/types/radix-ng-primitives-toolbar.d.ts +3 -2
- package/types/radix-ng-primitives-tooltip.d.ts +61 -80
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { InjectionToken, inject, signal, numberAttribute, DestroyRef, input, Directive, model, booleanAttribute, output, computed, effect, untracked, isDevMode,
|
|
3
|
-
import
|
|
2
|
+
import { InjectionToken, inject, signal, numberAttribute, DestroyRef, input, Directive, ElementRef, model, booleanAttribute, output, computed, effect, untracked, isDevMode, afterNextRender } from '@angular/core';
|
|
3
|
+
import * as i1$2 from '@radix-ng/primitives/core';
|
|
4
|
+
import { createContext, createFloatingRootContext, injectId, watch, createCancelableChangeEventDetails, provideFloatingTree, provideFloatingRootContext, rdxDevError, RDX_FLOATING_ROOT_CONTEXT, RDX_FLOATING_REGISTRATION, useGraceArea, RdxFloatingNodeRegistration } from '@radix-ng/primitives/core';
|
|
4
5
|
import * as i1 from '@radix-ng/primitives/popper';
|
|
5
|
-
import { RdxPopper, RdxPopperContentWrapper, RdxPopperArrow, RdxPopperContent, provideRdxPopperContentConfig, RdxPopperAnchor } from '@radix-ng/primitives/popper';
|
|
6
|
+
import { RdxPopper, RdxPopperContentWrapper, RdxPopperArrow, RdxPopperContent, provideRdxPopperContentWrapper, provideRdxPopperContentConfig, RdxPopperAnchor } from '@radix-ng/primitives/popper';
|
|
6
7
|
import { RdxVisuallyHiddenDirective } from '@radix-ng/primitives/visually-hidden';
|
|
7
8
|
import * as i1$1 from '@radix-ng/primitives/portal';
|
|
8
9
|
import { RdxPortalPresence } from '@radix-ng/primitives/portal';
|
|
9
10
|
import { provideRdxPresenceContext } from '@radix-ng/primitives/presence';
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import { RdxDismissableLayer } from '@radix-ng/primitives/dismissable-layer';
|
|
11
|
+
import { RdxDismiss } from '@radix-ng/primitives/dismissable-layer';
|
|
12
|
+
import { createRdxTriggerInteraction } from '@radix-ng/primitives/floating-focus-manager';
|
|
13
13
|
|
|
14
14
|
const defaultTooltipConfig = {
|
|
15
15
|
delay: 600,
|
|
@@ -133,6 +133,15 @@ class RdxTooltip {
|
|
|
133
133
|
this.popper = inject(RdxPopper);
|
|
134
134
|
this.destroyRef = inject(DestroyRef);
|
|
135
135
|
this.hasAppliedDefaultOpen = false;
|
|
136
|
+
/**
|
|
137
|
+
* Per-popup floating root context (ADR 0015) — the shared store the positioner's dismissal
|
|
138
|
+
* capability reads (`open`, `triggers`, the reference/floating elements). The tree node is
|
|
139
|
+
* registered by the positioner; this context exists independently so dismissal can read `open()`.
|
|
140
|
+
*/
|
|
141
|
+
this.floatingContext = createFloatingRootContext({
|
|
142
|
+
ownerDocument: inject(ElementRef).nativeElement.ownerDocument,
|
|
143
|
+
open: () => this.open()
|
|
144
|
+
});
|
|
136
145
|
/**
|
|
137
146
|
* Whether the tooltip is currently open.
|
|
138
147
|
*/
|
|
@@ -176,7 +185,10 @@ class RdxTooltip {
|
|
|
176
185
|
this.triggers = signal([], ...(ngDevMode ? [{ debugName: "triggers" }] : /* istanbul ignore next */ []));
|
|
177
186
|
this.payload = signal(undefined, ...(ngDevMode ? [{ debugName: "payload" }] : /* istanbul ignore next */ []));
|
|
178
187
|
this.cursorPosition = signal(undefined, ...(ngDevMode ? [{ debugName: "cursorPosition" }] : /* istanbul ignore next */ []));
|
|
188
|
+
this.openChangeReason = signal('none', ...(ngDevMode ? [{ debugName: "openChangeReason" }] : /* istanbul ignore next */ []));
|
|
189
|
+
this.preventUnmountOnClose = signal(false, ...(ngDevMode ? [{ debugName: "preventUnmountOnClose" }] : /* istanbul ignore next */ []));
|
|
179
190
|
this.openedInstant = signal(false, ...(ngDevMode ? [{ debugName: "openedInstant" }] : /* istanbul ignore next */ []));
|
|
191
|
+
this.suppressNextOpenChangeEmit = false;
|
|
180
192
|
/** Local instant window used when this tooltip is not inside a provider. */
|
|
181
193
|
this.localInstant = createTooltipInstantController(() => this.defaultConfig.timeout, this.destroyRef);
|
|
182
194
|
this.instantGroup = this.provider ?? this.localInstant;
|
|
@@ -190,6 +202,7 @@ class RdxTooltip {
|
|
|
190
202
|
this.defaultConfig.closeDelay, ...(ngDevMode ? [{ debugName: "resolvedCloseDelay" }] : /* istanbul ignore next */ []));
|
|
191
203
|
/** Whether the most recent open happened without the delay. */
|
|
192
204
|
this.instant = this.openedInstant.asReadonly();
|
|
205
|
+
this.present = computed(() => this.open() || this.preventUnmountOnClose(), ...(ngDevMode ? [{ debugName: "present" }] : /* istanbul ignore next */ []));
|
|
193
206
|
this.virtualAnchor = computed(() => {
|
|
194
207
|
const axis = this.trackCursorAxis();
|
|
195
208
|
const element = this.trigger();
|
|
@@ -213,7 +226,7 @@ class RdxTooltip {
|
|
|
213
226
|
}
|
|
214
227
|
};
|
|
215
228
|
}, ...(ngDevMode ? [{ debugName: "virtualAnchor" }] : /* istanbul ignore next */ []));
|
|
216
|
-
this.openTimer = useTimeoutFn(() => this.applyOpen(false), () => this.resolvedDelay(), { immediate: false }, this.destroyRef);
|
|
229
|
+
this.openTimer = useTimeoutFn(() => this.applyOpen(false, this.trigger(), this.payload(), 'trigger-hover'), () => this.resolvedDelay(), { immediate: false }, this.destroyRef);
|
|
217
230
|
this.closeTimer = useTimeoutFn(() => this.applyClose(), () => this.resolvedCloseDelay(), { immediate: false }, this.destroyRef);
|
|
218
231
|
effect(() => {
|
|
219
232
|
const defaultOpen = this.defaultOpen();
|
|
@@ -230,9 +243,19 @@ class RdxTooltip {
|
|
|
230
243
|
});
|
|
231
244
|
// Keep the popper anchored to the active trigger, or to the cursor while tracking.
|
|
232
245
|
effect(() => this.popper.anchorOverride.set(this.virtualAnchor()));
|
|
246
|
+
// Sync the dismissal reference (the active trigger) so an outside-press on the trigger counts
|
|
247
|
+
// as "inside" and never dismisses (ADR 0015).
|
|
248
|
+
effect(() => this.floatingContext.setReferenceElement(this.trigger() ?? null));
|
|
233
249
|
watch([this.open], ([isOpen]) => {
|
|
234
|
-
this.
|
|
250
|
+
if (this.suppressNextOpenChangeEmit) {
|
|
251
|
+
this.suppressNextOpenChangeEmit = false;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
const { eventDetails } = createCancelableChangeEventDetails(this.openChangeReason(), new Event('tooltip.open-change'), this.trigger());
|
|
255
|
+
this.onOpenChange.emit({ open: isOpen, eventDetails });
|
|
256
|
+
}
|
|
235
257
|
if (isOpen) {
|
|
258
|
+
this.preventUnmountOnClose.set(false);
|
|
236
259
|
this.instantGroup.onOpen();
|
|
237
260
|
}
|
|
238
261
|
else {
|
|
@@ -242,26 +265,36 @@ class RdxTooltip {
|
|
|
242
265
|
}, { defer: true });
|
|
243
266
|
}
|
|
244
267
|
/** Opens immediately, optionally switching the active trigger/payload. */
|
|
245
|
-
show(trigger = this.trigger(), payload) {
|
|
246
|
-
this.applyOpen(true, trigger, payload);
|
|
268
|
+
show(trigger = this.trigger(), payload, event) {
|
|
269
|
+
this.applyOpen(true, trigger, payload, 'trigger-focus', event);
|
|
247
270
|
}
|
|
248
|
-
close() {
|
|
271
|
+
close(reason = 'none', event) {
|
|
272
|
+
this.openTimer.stop();
|
|
273
|
+
this.closeTimer.stop();
|
|
274
|
+
this.applyClose(reason, event);
|
|
275
|
+
}
|
|
276
|
+
cancelPendingOpen() {
|
|
277
|
+
this.openTimer.stop();
|
|
278
|
+
}
|
|
279
|
+
closeHoverOpen(event) {
|
|
249
280
|
this.openTimer.stop();
|
|
250
281
|
this.closeTimer.stop();
|
|
251
|
-
this.
|
|
282
|
+
if (this.open() && this.openChangeReason() === 'trigger-hover') {
|
|
283
|
+
this.applyClose('trigger-hover', event);
|
|
284
|
+
}
|
|
252
285
|
}
|
|
253
286
|
/** Closes after the resolved close delay, e.g. when the pointer or focus leaves. */
|
|
254
|
-
scheduleClose() {
|
|
287
|
+
scheduleClose(event) {
|
|
255
288
|
this.openTimer.stop();
|
|
256
289
|
if (this.resolvedCloseDelay() <= 0) {
|
|
257
|
-
this.applyClose();
|
|
290
|
+
this.applyClose('trigger-hover', event);
|
|
258
291
|
}
|
|
259
292
|
else {
|
|
260
293
|
this.closeTimer.start();
|
|
261
294
|
}
|
|
262
295
|
}
|
|
263
296
|
/** Hover/focus entered — open after the delay, or instantly within the instant window. */
|
|
264
|
-
onTriggerEnter(trigger = this.trigger(), payload) {
|
|
297
|
+
onTriggerEnter(trigger = this.trigger(), payload, event) {
|
|
265
298
|
if (this.disabled()) {
|
|
266
299
|
return;
|
|
267
300
|
}
|
|
@@ -271,7 +304,7 @@ class RdxTooltip {
|
|
|
271
304
|
this.payload.set(payload);
|
|
272
305
|
this.closeTimer.stop();
|
|
273
306
|
if (this.instantGroup.isInstant() || this.resolvedDelay() <= 0) {
|
|
274
|
-
this.applyOpen(true, trigger, payload);
|
|
307
|
+
this.applyOpen(true, trigger, payload, 'trigger-hover', event);
|
|
275
308
|
}
|
|
276
309
|
else {
|
|
277
310
|
this.openTimer.start();
|
|
@@ -286,16 +319,18 @@ class RdxTooltip {
|
|
|
286
319
|
}
|
|
287
320
|
registerTrigger(trigger) {
|
|
288
321
|
this.triggers.update((triggers) => (triggers.includes(trigger) ? triggers : [...triggers, trigger]));
|
|
322
|
+
this.floatingContext.triggers.add(trigger);
|
|
289
323
|
if (!this.trigger()) {
|
|
290
324
|
this.trigger.set(trigger);
|
|
291
325
|
}
|
|
292
326
|
return () => {
|
|
293
327
|
this.triggers.update((triggers) => triggers.filter((candidate) => candidate !== trigger));
|
|
328
|
+
this.floatingContext.triggers.delete(trigger);
|
|
294
329
|
if (this.trigger() === trigger) {
|
|
295
330
|
const nextTrigger = this.triggers()[0];
|
|
296
331
|
this.trigger.set(nextTrigger);
|
|
297
332
|
if (!nextTrigger && !this.destroyRef.destroyed) {
|
|
298
|
-
this.applyClose();
|
|
333
|
+
this.applyClose('none');
|
|
299
334
|
}
|
|
300
335
|
}
|
|
301
336
|
};
|
|
@@ -308,12 +343,21 @@ class RdxTooltip {
|
|
|
308
343
|
this.triggerDelay.set(delay);
|
|
309
344
|
this.triggerCloseDelay.set(closeDelay);
|
|
310
345
|
}
|
|
311
|
-
applyOpen(instant, trigger = this.trigger(), payload) {
|
|
346
|
+
applyOpen(instant, trigger = this.trigger(), payload, reason = 'none', event) {
|
|
312
347
|
if (this.disabled()) {
|
|
313
348
|
return;
|
|
314
349
|
}
|
|
350
|
+
const wasOpen = this.open();
|
|
315
351
|
this.openTimer.stop();
|
|
316
352
|
this.closeTimer.stop();
|
|
353
|
+
if (!wasOpen) {
|
|
354
|
+
const { eventDetails } = createCancelableChangeEventDetails(reason, event ?? new Event('tooltip.open-change'), trigger);
|
|
355
|
+
this.onOpenChange.emit({ open: true, eventDetails });
|
|
356
|
+
if (eventDetails.isCanceled()) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
this.suppressNextOpenChangeEmit = true;
|
|
360
|
+
}
|
|
317
361
|
if (trigger) {
|
|
318
362
|
this.trigger.set(trigger);
|
|
319
363
|
}
|
|
@@ -321,21 +365,43 @@ class RdxTooltip {
|
|
|
321
365
|
this.payload.set(payload);
|
|
322
366
|
}
|
|
323
367
|
this.openedInstant.set(instant || this.instantGroup.isInstant());
|
|
368
|
+
this.preventUnmountOnClose.set(false);
|
|
369
|
+
this.openChangeReason.set(reason);
|
|
324
370
|
this.open.set(true);
|
|
325
371
|
}
|
|
326
|
-
applyClose() {
|
|
372
|
+
applyClose(reason = 'none', event) {
|
|
373
|
+
if (!this.open()) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const change = createCancelableChangeEventDetails(reason, event ?? new Event('tooltip.open-change'), this.trigger());
|
|
377
|
+
const { eventDetails } = change;
|
|
378
|
+
this.onOpenChange.emit({ open: false, eventDetails });
|
|
379
|
+
if (eventDetails.isCanceled()) {
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
this.suppressNextOpenChangeEmit = true;
|
|
383
|
+
this.preventUnmountOnClose.set(change.shouldPreventUnmountOnClose());
|
|
327
384
|
this.openedInstant.set(this.instantGroup.isInstant());
|
|
385
|
+
this.openChangeReason.set(reason);
|
|
328
386
|
this.open.set(false);
|
|
329
387
|
}
|
|
330
388
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltip, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
331
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltip, isStandalone: true, selector: "[rdxTooltip]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, disableHoverablePopup: { classPropertyName: "disableHoverablePopup", publicName: "disableHoverablePopup", isSignal: true, isRequired: false, transformFunction: null }, trackCursorAxis: { classPropertyName: "trackCursorAxis", publicName: "trackCursorAxis", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", onOpenChange: "onOpenChange" }, providers: [
|
|
389
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltip, isStandalone: true, selector: "[rdxTooltip]", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, defaultOpen: { classPropertyName: "defaultOpen", publicName: "defaultOpen", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, disableHoverablePopup: { classPropertyName: "disableHoverablePopup", publicName: "disableHoverablePopup", isSignal: true, isRequired: false, transformFunction: null }, trackCursorAxis: { classPropertyName: "trackCursorAxis", publicName: "trackCursorAxis", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", onOpenChange: "onOpenChange" }, providers: [
|
|
390
|
+
provideRdxTooltipContext(context),
|
|
391
|
+
provideFloatingTree(),
|
|
392
|
+
provideFloatingRootContext(() => inject(RdxTooltip).floatingContext)
|
|
393
|
+
], exportAs: ["rdxTooltip"], hostDirectives: [{ directive: i1.RdxPopper }], ngImport: i0 }); }
|
|
332
394
|
}
|
|
333
395
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltip, decorators: [{
|
|
334
396
|
type: Directive,
|
|
335
397
|
args: [{
|
|
336
398
|
selector: '[rdxTooltip]',
|
|
337
399
|
exportAs: 'rdxTooltip',
|
|
338
|
-
providers: [
|
|
400
|
+
providers: [
|
|
401
|
+
provideRdxTooltipContext(context),
|
|
402
|
+
provideFloatingTree(),
|
|
403
|
+
provideFloatingRootContext(() => inject(RdxTooltip).floatingContext)
|
|
404
|
+
],
|
|
339
405
|
hostDirectives: [RdxPopper]
|
|
340
406
|
}]
|
|
341
407
|
}], 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 }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], disableHoverablePopup: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableHoverablePopup", required: false }] }], trackCursorAxis: [{ type: i0.Input, args: [{ isSignal: true, alias: "trackCursorAxis", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], handle: [{ type: i0.Input, args: [{ isSignal: true, alias: "handle", required: false }] }], onOpenChange: [{ type: i0.Output, args: ["onOpenChange"] }] } });
|
|
@@ -343,6 +409,7 @@ function contextFor(root) {
|
|
|
343
409
|
return {
|
|
344
410
|
contentId: root.contentId,
|
|
345
411
|
isOpen: root.open,
|
|
412
|
+
present: root.present,
|
|
346
413
|
instant: root.instant,
|
|
347
414
|
disabled: root.disabled,
|
|
348
415
|
disableHoverablePopup: root.disableHoverablePopup,
|
|
@@ -350,11 +417,14 @@ function contextFor(root) {
|
|
|
350
417
|
trigger: root.trigger.asReadonly(),
|
|
351
418
|
triggers: root.triggers.asReadonly(),
|
|
352
419
|
payload: root.payload.asReadonly(),
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
420
|
+
openChangeReason: root.openChangeReason.asReadonly(),
|
|
421
|
+
open: (trigger, payload, event) => root.show(trigger, payload, event),
|
|
422
|
+
close: (reason, event) => root.close(reason, event),
|
|
423
|
+
cancelPendingOpen: () => root.cancelPendingOpen(),
|
|
424
|
+
closeHoverOpen: (event) => root.closeHoverOpen(event),
|
|
425
|
+
closeDelayed: (event) => root.scheduleClose(event),
|
|
356
426
|
registerTrigger: (trigger) => root.registerTrigger(trigger),
|
|
357
|
-
onTriggerEnter: (trigger, payload) => root.onTriggerEnter(trigger, payload),
|
|
427
|
+
onTriggerEnter: (trigger, payload, event) => root.onTriggerEnter(trigger, payload, event),
|
|
358
428
|
onTriggerLeave: () => root.onTriggerLeave(),
|
|
359
429
|
setCursorPosition: (position) => root.setCursorPosition(position),
|
|
360
430
|
setDelays: (delay, closeDelay) => root.setDelays(delay, closeDelay)
|
|
@@ -431,7 +501,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
431
501
|
*/
|
|
432
502
|
class RdxTooltipPortal {
|
|
433
503
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortal, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
434
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipPortal, isStandalone: true, selector: "ng-template[rdxTooltipPortal]", providers: [provideRdxPresenceContext(() => ({ present: injectRdxTooltipContext().
|
|
504
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipPortal, isStandalone: true, selector: "ng-template[rdxTooltipPortal]", providers: [provideRdxPresenceContext(() => ({ present: injectRdxTooltipContext().present }))], exportAs: ["rdxTooltipPortal"], hostDirectives: [{ directive: i1$1.RdxPortalPresence, inputs: ["container", "container"] }], ngImport: i0 }); }
|
|
435
505
|
}
|
|
436
506
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortal, decorators: [{
|
|
437
507
|
type: Directive,
|
|
@@ -439,7 +509,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
439
509
|
selector: 'ng-template[rdxTooltipPortal]',
|
|
440
510
|
exportAs: 'rdxTooltipPortal',
|
|
441
511
|
hostDirectives: [{ directive: RdxPortalPresence, inputs: ['container'] }],
|
|
442
|
-
providers: [provideRdxPresenceContext(() => ({ present: injectRdxTooltipContext().
|
|
512
|
+
providers: [provideRdxPresenceContext(() => ({ present: injectRdxTooltipContext().present }))]
|
|
443
513
|
}]
|
|
444
514
|
}] });
|
|
445
515
|
/**
|
|
@@ -450,9 +520,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
450
520
|
class RdxTooltipPortalMisuseGuard {
|
|
451
521
|
constructor() {
|
|
452
522
|
if (isDevMode()) {
|
|
453
|
-
|
|
523
|
+
rdxDevError('tooltip/portal-on-element', '`rdxTooltipPortal` is now a structural directive. ' +
|
|
454
524
|
'Use `*rdxTooltipPortal` on the positioner element or `<ng-template rdxTooltipPortal>`. ' +
|
|
455
|
-
'rdxTooltipPortalPresence has been removed.
|
|
525
|
+
'rdxTooltipPortalPresence has been removed.', 'components/tooltip');
|
|
456
526
|
}
|
|
457
527
|
}
|
|
458
528
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPortalMisuseGuard, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
@@ -467,89 +537,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
467
537
|
|
|
468
538
|
/**
|
|
469
539
|
* Positions the tooltip popup against its trigger (or a custom anchor).
|
|
540
|
+
*
|
|
541
|
+
* A "thin" positioner (ADR 0012): it inherits the popper positioning surface (inputs, `placed`
|
|
542
|
+
* output, unified vars + placement attrs) from {@link RdxPopperContentWrapper} and adds tooltip's own
|
|
543
|
+
* concerns — Base UI-aligned defaults (`side: 'top'`) via the config provider, dismiss handling
|
|
544
|
+
* (ADR 0015 — inline {@link RdxDismiss} on the shared floating tree, dismissal-only with
|
|
545
|
+
* no focus manager), the cursor-follow pointer-through behavior (via the inherited `nonInteractive`
|
|
546
|
+
* signal), the open/closed state attributes, and the hover grace area.
|
|
470
547
|
*/
|
|
471
|
-
class RdxTooltipPositioner {
|
|
548
|
+
class RdxTooltipPositioner extends RdxPopperContentWrapper {
|
|
472
549
|
constructor() {
|
|
550
|
+
super();
|
|
473
551
|
this.rootContext = injectRdxTooltipContext();
|
|
474
|
-
this.wrapper = inject(RdxPopperContentWrapper);
|
|
475
552
|
this.destroyRef = inject(DestroyRef);
|
|
476
|
-
this.
|
|
477
|
-
this.
|
|
478
|
-
|
|
479
|
-
* An element to position the popup against. Defaults to the trigger.
|
|
480
|
-
*/
|
|
481
|
-
this.anchor = input(...(ngDevMode ? [undefined, { debugName: "anchor" }] : /* istanbul ignore next */ []));
|
|
482
|
-
/**
|
|
483
|
-
* The preferred side of the anchor to render against when open.
|
|
484
|
-
*/
|
|
485
|
-
this.side = input('top', ...(ngDevMode ? [{ debugName: "side" }] : /* istanbul ignore next */ []));
|
|
486
|
-
/**
|
|
487
|
-
* The distance in pixels from the anchor.
|
|
488
|
-
*/
|
|
489
|
-
this.sideOffset = input(0, { ...(ngDevMode ? { debugName: "sideOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
490
|
-
/**
|
|
491
|
-
* The preferred alignment against the anchor.
|
|
492
|
-
*/
|
|
493
|
-
this.align = input('center', ...(ngDevMode ? [{ debugName: "align" }] : /* istanbul ignore next */ []));
|
|
494
|
-
/**
|
|
495
|
-
* An offset in pixels from the `start` or `end` alignment options.
|
|
496
|
-
*/
|
|
497
|
-
this.alignOffset = input(0, { ...(ngDevMode ? { debugName: "alignOffset" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
498
|
-
/**
|
|
499
|
-
* The padding between the arrow and the edges of the content.
|
|
500
|
-
*/
|
|
501
|
-
this.arrowPadding = input(5, { ...(ngDevMode ? { debugName: "arrowPadding" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
502
|
-
/**
|
|
503
|
-
* When `true`, overrides the `side` and `align` preferences to prevent collisions with boundary edges.
|
|
504
|
-
*/
|
|
505
|
-
this.avoidCollisions = input(true, { ...(ngDevMode ? { debugName: "avoidCollisions" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
506
|
-
/**
|
|
507
|
-
* The element used as the collision boundary.
|
|
508
|
-
*/
|
|
509
|
-
this.collisionBoundary = input(...(ngDevMode ? [undefined, { debugName: "collisionBoundary" }] : /* istanbul ignore next */ []));
|
|
510
|
-
/**
|
|
511
|
-
* The distance in pixels from the boundary edges where collision detection should occur.
|
|
512
|
-
*/
|
|
513
|
-
this.collisionPadding = input(5, ...(ngDevMode ? [{ debugName: "collisionPadding" }] : /* istanbul ignore next */ []));
|
|
514
|
-
/**
|
|
515
|
-
* The sticky behavior on the `align` axis.
|
|
516
|
-
*/
|
|
517
|
-
this.sticky = input('partial', ...(ngDevMode ? [{ debugName: "sticky" }] : /* istanbul ignore next */ []));
|
|
518
|
-
/**
|
|
519
|
-
* Whether to hide the content when the trigger becomes fully occluded.
|
|
520
|
-
*/
|
|
521
|
-
this.hideWhenDetached = input(false, { ...(ngDevMode ? { debugName: "hideWhenDetached" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
522
|
-
/**
|
|
523
|
-
* The CSS position strategy used by Floating UI.
|
|
524
|
-
*/
|
|
525
|
-
this.positionStrategy = input('fixed', ...(ngDevMode ? [{ debugName: "positionStrategy" }] : /* istanbul ignore next */ []));
|
|
526
|
-
/**
|
|
527
|
-
* Whether to update the position of the floating element on every animation frame if required.
|
|
528
|
-
*/
|
|
529
|
-
this.updatePositionStrategy = input('always', ...(ngDevMode ? [{ debugName: "updatePositionStrategy" }] : /* istanbul ignore next */ []));
|
|
530
|
-
/**
|
|
531
|
-
* Emits when the element is placed.
|
|
532
|
-
*/
|
|
533
|
-
this.placed = outputFromObservable(outputToObservable(this.wrapper.placed));
|
|
553
|
+
this.floatingContext = inject(RDX_FLOATING_ROOT_CONTEXT);
|
|
554
|
+
this.registration = inject(RDX_FLOATING_REGISTRATION, { optional: true });
|
|
555
|
+
this.containerRef = inject(ElementRef);
|
|
534
556
|
/**
|
|
535
557
|
* Event handler called when the escape key is down. Can be prevented.
|
|
536
558
|
*/
|
|
537
|
-
this.escapeKeyDown =
|
|
559
|
+
this.escapeKeyDown = output();
|
|
538
560
|
/**
|
|
539
|
-
* Event handler called when a `pointerdown` event happens outside of the
|
|
561
|
+
* Event handler called when a `pointerdown` event happens outside of the popup. Can be prevented.
|
|
540
562
|
*/
|
|
541
|
-
this.pointerDownOutside =
|
|
563
|
+
this.pointerDownOutside = output();
|
|
542
564
|
this.triggerEl = signal(null, ...(ngDevMode ? [{ debugName: "triggerEl" }] : /* istanbul ignore next */ []));
|
|
543
565
|
this.containerEl = signal(null, ...(ngDevMode ? [{ debugName: "containerEl" }] : /* istanbul ignore next */ []));
|
|
544
566
|
this.graceArea = useGraceArea(this.triggerEl, this.containerEl, 300);
|
|
545
567
|
this.afterNextRender = afterNextRender(() => {
|
|
546
568
|
this.triggerEl.set(this.rootContext.trigger() ?? null);
|
|
547
|
-
this.containerEl.set(this.
|
|
569
|
+
this.containerEl.set(this.containerRef.nativeElement);
|
|
548
570
|
const handleScroll = (event) => {
|
|
549
571
|
const target = event.target;
|
|
550
572
|
const trigger = this.rootContext.trigger();
|
|
551
573
|
if (trigger && target?.contains(trigger)) {
|
|
552
|
-
this.rootContext.close();
|
|
574
|
+
this.rootContext.close('none', event);
|
|
553
575
|
}
|
|
554
576
|
};
|
|
555
577
|
window.addEventListener('scroll', handleScroll, { capture: true });
|
|
@@ -566,58 +588,77 @@ class RdxTooltipPositioner {
|
|
|
566
588
|
this.rootContext.closeDelayed();
|
|
567
589
|
});
|
|
568
590
|
});
|
|
569
|
-
|
|
570
|
-
|
|
591
|
+
// Register as the floating element so dismissal containment (outside-press / focus) treats the
|
|
592
|
+
// popup as "inside".
|
|
593
|
+
this.floatingContext.setFloatingElement(this.containerRef.nativeElement);
|
|
594
|
+
// Dismissal-only (ADR 0017 §1 — a tooltip has no focus manager): Escape and an outside press
|
|
595
|
+
// close it; focus-out is intentionally a no-op (a tooltip never traps or follows focus).
|
|
596
|
+
new RdxDismiss(this.floatingContext, () => this.registration?.node() ?? null, {
|
|
597
|
+
escapeKey: () => true,
|
|
598
|
+
outsidePress: () => true,
|
|
599
|
+
focusOutside: () => false,
|
|
600
|
+
onEscapeKeyDown: (event) => this.escapeKeyDown.emit(event),
|
|
601
|
+
onPointerDownOutside: (event) => this.pointerDownOutside.emit(event),
|
|
602
|
+
onDismiss: (reason, event) => this.rootContext.close(reason === 'escape-key' ? 'escape-key' : 'outside-press', event)
|
|
603
|
+
});
|
|
571
604
|
// While following the cursor the popup sits right under the pointer; if it could intercept
|
|
572
605
|
// the pointer it would steal hover from the trigger and the tooltip would flicker. Render it
|
|
573
606
|
// pointer-events: none so the pointer always passes through to the trigger underneath.
|
|
574
|
-
effect(() => this.
|
|
607
|
+
effect(() => this.nonInteractive.set(this.rootContext.trackCursorAxis() !== 'none'));
|
|
575
608
|
}
|
|
576
609
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPositioner, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
577
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "
|
|
610
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.9", type: RdxTooltipPositioner, isStandalone: true, selector: "[rdxTooltipPositioner]", outputs: { escapeKeyDown: "escapeKeyDown", pointerDownOutside: "pointerDownOutside" }, host: { properties: { "attr.data-open": "rootContext.isOpen() ? \"\" : undefined", "attr.data-closed": "rootContext.isOpen() ? undefined : \"\"" } }, providers: [
|
|
611
|
+
...provideRdxPopperContentWrapper(RdxTooltipPositioner),
|
|
612
|
+
provideRdxPopperContentConfig({ side: 'top', arrowPadding: 5, collisionPadding: 5 })
|
|
613
|
+
], usesInheritance: true, hostDirectives: [{ directive: i1$2.RdxFloatingNodeRegistration }], ngImport: i0 }); }
|
|
578
614
|
}
|
|
579
615
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipPositioner, decorators: [{
|
|
580
616
|
type: Directive,
|
|
581
617
|
args: [{
|
|
582
618
|
selector: '[rdxTooltipPositioner]',
|
|
583
|
-
providers: [
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
{
|
|
587
|
-
directive: RdxPopperContentWrapper,
|
|
588
|
-
inputs: [
|
|
589
|
-
'anchor',
|
|
590
|
-
'side',
|
|
591
|
-
'sideOffset',
|
|
592
|
-
'align',
|
|
593
|
-
'alignOffset',
|
|
594
|
-
'arrowPadding',
|
|
595
|
-
'avoidCollisions',
|
|
596
|
-
'collisionBoundary',
|
|
597
|
-
'collisionPadding',
|
|
598
|
-
'sticky',
|
|
599
|
-
'hideWhenDetached',
|
|
600
|
-
'positionStrategy',
|
|
601
|
-
'updatePositionStrategy'
|
|
602
|
-
]
|
|
603
|
-
}
|
|
619
|
+
providers: [
|
|
620
|
+
...provideRdxPopperContentWrapper(RdxTooltipPositioner),
|
|
621
|
+
provideRdxPopperContentConfig({ side: 'top', arrowPadding: 5, collisionPadding: 5 })
|
|
604
622
|
],
|
|
623
|
+
hostDirectives: [RdxFloatingNodeRegistration],
|
|
605
624
|
host: {
|
|
606
625
|
'[attr.data-open]': 'rootContext.isOpen() ? "" : undefined',
|
|
607
|
-
'[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""'
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
'[style]': `{
|
|
611
|
-
'--anchor-width': 'var(--radix-popper-anchor-width)',
|
|
612
|
-
'--anchor-height': 'var(--radix-popper-anchor-height)',
|
|
613
|
-
'--available-width': 'var(--radix-popper-available-width)',
|
|
614
|
-
'--available-height': 'var(--radix-popper-available-height)',
|
|
615
|
-
'--transform-origin': 'var(--radix-popper-transform-origin)'
|
|
616
|
-
}`
|
|
626
|
+
'[attr.data-closed]': 'rootContext.isOpen() ? undefined : ""'
|
|
627
|
+
// `data-side`/`data-align`/`data-anchor-hidden` and the unified vars come from the inherited
|
|
628
|
+
// wrapper (ADR 0012); tooltip exposes no legacy `--radix-*` aliases.
|
|
617
629
|
}
|
|
618
630
|
}]
|
|
619
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
631
|
+
}], ctorParameters: () => [], propDecorators: { escapeKeyDown: [{ type: i0.Output, args: ["escapeKeyDown"] }], pointerDownOutside: [{ type: i0.Output, args: ["pointerDownOutside"] }] } });
|
|
620
632
|
|
|
633
|
+
const TOOLTIP_TRIGGER_ATTR = 'data-rdx-tooltip-trigger';
|
|
634
|
+
function getTargetElement(event) {
|
|
635
|
+
if ('composedPath' in event) {
|
|
636
|
+
for (const target of event.composedPath()) {
|
|
637
|
+
if (target instanceof Element) {
|
|
638
|
+
return target;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
return event.target instanceof Element ? event.target : null;
|
|
643
|
+
}
|
|
644
|
+
function closestEnabledTooltipTrigger(element) {
|
|
645
|
+
let current = element;
|
|
646
|
+
while (current) {
|
|
647
|
+
if (current.hasAttribute(TOOLTIP_TRIGGER_ATTR)) {
|
|
648
|
+
return current;
|
|
649
|
+
}
|
|
650
|
+
if (current.parentElement) {
|
|
651
|
+
current = current.parentElement;
|
|
652
|
+
continue;
|
|
653
|
+
}
|
|
654
|
+
const root = current.getRootNode();
|
|
655
|
+
current = 'host' in root && root.host instanceof Element ? root.host : null;
|
|
656
|
+
}
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
function isMouseLikePointerType(pointerType) {
|
|
660
|
+
return pointerType !== 'touch';
|
|
661
|
+
}
|
|
621
662
|
class RdxTooltipTrigger {
|
|
622
663
|
constructor() {
|
|
623
664
|
this.parentRootContext = injectRdxTooltipContext(true);
|
|
@@ -660,8 +701,16 @@ class RdxTooltipTrigger {
|
|
|
660
701
|
this.isDisabled = computed(() => (this.rootContext()?.disabled() ?? false) || this.disabled(), ...(ngDevMode ? [{ debugName: "isDisabled" }] : /* istanbul ignore next */ []));
|
|
661
702
|
/** Whether this specific trigger is the active anchor of an open tooltip. */
|
|
662
703
|
this.isOpen = computed(() => this.rootContext()?.isOpen() === true && this.rootContext()?.trigger() === this.elementRef.nativeElement, ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
704
|
+
this.triggerInteraction = createRdxTriggerInteraction({
|
|
705
|
+
trigger: () => this.elementRef.nativeElement,
|
|
706
|
+
activeTrigger: () => this.rootContext()?.trigger(),
|
|
707
|
+
open: () => this.rootContext()?.isOpen() ?? false,
|
|
708
|
+
disabled: () => this.isDisabled(),
|
|
709
|
+
contentId: () => this.rootContext()?.contentId
|
|
710
|
+
});
|
|
663
711
|
this.isPointerDown = signal(false, ...(ngDevMode ? [{ debugName: "isPointerDown" }] : /* istanbul ignore next */ []));
|
|
664
712
|
this.hasPointerMoveOpened = signal(false, ...(ngDevMode ? [{ debugName: "hasPointerMoveOpened" }] : /* istanbul ignore next */ []));
|
|
713
|
+
this.isNestedTriggerHovered = signal(false, ...(ngDevMode ? [{ debugName: "isNestedTriggerHovered" }] : /* istanbul ignore next */ []));
|
|
665
714
|
effect((onCleanup) => {
|
|
666
715
|
const handle = this.handle();
|
|
667
716
|
if (handle) {
|
|
@@ -672,22 +721,29 @@ class RdxTooltipTrigger {
|
|
|
672
721
|
}
|
|
673
722
|
});
|
|
674
723
|
}
|
|
675
|
-
handleFocus() {
|
|
724
|
+
handleFocus(event) {
|
|
676
725
|
const rootContext = this.rootContext();
|
|
677
726
|
if (!rootContext || this.isDisabled() || this.isPointerDown()) {
|
|
678
727
|
return;
|
|
679
728
|
}
|
|
680
729
|
rootContext.setDelays(this.delay(), this.closeDelay());
|
|
681
|
-
rootContext.open(this.elementRef.nativeElement, this.payload());
|
|
730
|
+
rootContext.open(this.elementRef.nativeElement, this.payload(), event);
|
|
682
731
|
}
|
|
683
|
-
handleBlur() {
|
|
684
|
-
this.rootContext()?.closeDelayed();
|
|
732
|
+
handleBlur(event) {
|
|
733
|
+
this.rootContext()?.closeDelayed(event);
|
|
685
734
|
}
|
|
686
|
-
handleClick() {
|
|
735
|
+
handleClick(event) {
|
|
687
736
|
const rootContext = this.rootContext();
|
|
688
737
|
if (rootContext?.isOpen() && this.closeOnClick()) {
|
|
689
|
-
rootContext.close();
|
|
738
|
+
rootContext.close('trigger-press', event);
|
|
739
|
+
return;
|
|
690
740
|
}
|
|
741
|
+
if (rootContext && this.closeOnClick()) {
|
|
742
|
+
rootContext.cancelPendingOpen();
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
handlePointerEnter(event) {
|
|
746
|
+
this.pointerType = event.pointerType;
|
|
691
747
|
}
|
|
692
748
|
handlePointerMove(event) {
|
|
693
749
|
if (event.pointerType === 'touch') {
|
|
@@ -697,12 +753,16 @@ class RdxTooltipTrigger {
|
|
|
697
753
|
if (!rootContext || this.isDisabled()) {
|
|
698
754
|
return;
|
|
699
755
|
}
|
|
756
|
+
this.pointerType = event.pointerType;
|
|
757
|
+
if (this.detectNestedTriggerHover(getTargetElement(event))) {
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
700
760
|
if (rootContext.trackCursorAxis() !== 'none') {
|
|
701
761
|
rootContext.setCursorPosition({ x: event.clientX, y: event.clientY });
|
|
702
762
|
}
|
|
703
763
|
if (!this.hasPointerMoveOpened()) {
|
|
704
764
|
rootContext.setDelays(this.delay(), this.closeDelay());
|
|
705
|
-
rootContext.onTriggerEnter(this.elementRef.nativeElement, this.payload());
|
|
765
|
+
rootContext.onTriggerEnter(this.elementRef.nativeElement, this.payload(), event);
|
|
706
766
|
this.hasPointerMoveOpened.set(true);
|
|
707
767
|
}
|
|
708
768
|
}
|
|
@@ -710,6 +770,35 @@ class RdxTooltipTrigger {
|
|
|
710
770
|
this.rootContext()?.onTriggerLeave();
|
|
711
771
|
this.hasPointerMoveOpened.set(false);
|
|
712
772
|
}
|
|
773
|
+
handleMouseOver(event) {
|
|
774
|
+
const wasNestedTriggerHovered = this.isNestedTriggerHovered();
|
|
775
|
+
const target = getTargetElement(event);
|
|
776
|
+
const nestedTriggerHovered = this.detectNestedTriggerHover(target);
|
|
777
|
+
const trigger = this.elementRef.nativeElement;
|
|
778
|
+
const targetInsideTrigger = target ? trigger.contains(target) : false;
|
|
779
|
+
const rootContext = this.rootContext();
|
|
780
|
+
if (!rootContext) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
783
|
+
if (nestedTriggerHovered && rootContext.isOpen() && rootContext.openChangeReason() === 'trigger-hover') {
|
|
784
|
+
rootContext.closeHoverOpen();
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
if (wasNestedTriggerHovered &&
|
|
788
|
+
!nestedTriggerHovered &&
|
|
789
|
+
targetInsideTrigger &&
|
|
790
|
+
!this.isDisabled() &&
|
|
791
|
+
!rootContext.isOpen() &&
|
|
792
|
+
isMouseLikePointerType(this.pointerType)) {
|
|
793
|
+
rootContext.setDelays(this.delay(), this.closeDelay());
|
|
794
|
+
rootContext.onTriggerEnter(trigger, this.payload(), event);
|
|
795
|
+
this.hasPointerMoveOpened.set(true);
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
handleMouseLeave() {
|
|
799
|
+
this.isNestedTriggerHovered.set(false);
|
|
800
|
+
this.pointerType = undefined;
|
|
801
|
+
}
|
|
713
802
|
async handlePointerDown(event) {
|
|
714
803
|
const user = this.userOnPointerDown();
|
|
715
804
|
let result;
|
|
@@ -722,13 +811,28 @@ class RdxTooltipTrigger {
|
|
|
722
811
|
return;
|
|
723
812
|
}
|
|
724
813
|
this.isPointerDown.set(true);
|
|
814
|
+
this.triggerInteraction.recordPointerDown(event);
|
|
815
|
+
this.pointerType = event.pointerType;
|
|
816
|
+
if (this.closeOnClick() && !this.rootContext()?.isOpen()) {
|
|
817
|
+
this.rootContext()?.cancelPendingOpen();
|
|
818
|
+
}
|
|
725
819
|
const handlePointerUp = () => {
|
|
726
820
|
setTimeout(() => this.isPointerDown.set(false), 1);
|
|
727
821
|
};
|
|
728
822
|
document.addEventListener('pointerup', handlePointerUp, { once: true });
|
|
729
823
|
}
|
|
824
|
+
detectNestedTriggerHover(target) {
|
|
825
|
+
const trigger = this.elementRef.nativeElement;
|
|
826
|
+
const nearestTrigger = closestEnabledTooltipTrigger(target);
|
|
827
|
+
const nestedTriggerHovered = nearestTrigger !== null && nearestTrigger !== trigger && trigger.contains(nearestTrigger);
|
|
828
|
+
this.isNestedTriggerHovered.set(nestedTriggerHovered);
|
|
829
|
+
if (nestedTriggerHovered) {
|
|
830
|
+
this.rootContext()?.cancelPendingOpen();
|
|
831
|
+
}
|
|
832
|
+
return nestedTriggerHovered;
|
|
833
|
+
}
|
|
730
834
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
731
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipTrigger, isStandalone: true, selector: "[rdxTooltipTrigger]", inputs: { handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null }, payload: { classPropertyName: "payload", publicName: "payload", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, userOnPointerDown: { classPropertyName: "userOnPointerDown", publicName: "rdxOnPointerDown", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button", "data-grace-area-trigger": "''" }, listeners: { "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave()", "pointerdown": "handlePointerDown($event)", "focus": "handleFocus()", "blur": "handleBlur()", "click": "handleClick()" }, properties: { "id": "triggerId()", "attr.aria-describedby": "isOpen() ? rootContext()?.contentId : undefined", "attr.data-popup-open": "
|
|
835
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.9", type: RdxTooltipTrigger, isStandalone: true, selector: "[rdxTooltipTrigger]", inputs: { handle: { classPropertyName: "handle", publicName: "handle", isSignal: true, isRequired: false, transformFunction: null }, payload: { classPropertyName: "payload", publicName: "payload", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, closeOnClick: { classPropertyName: "closeOnClick", publicName: "closeOnClick", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, delay: { classPropertyName: "delay", publicName: "delay", isSignal: true, isRequired: false, transformFunction: null }, closeDelay: { classPropertyName: "closeDelay", publicName: "closeDelay", isSignal: true, isRequired: false, transformFunction: null }, userOnPointerDown: { classPropertyName: "userOnPointerDown", publicName: "rdxOnPointerDown", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "type": "button", "data-grace-area-trigger": "''" }, listeners: { "pointerenter": "handlePointerEnter($event)", "pointermove": "handlePointerMove($event)", "pointerleave": "handlePointerLeave()", "mouseover": "handleMouseOver($event)", "mouseleave": "handleMouseLeave()", "pointerdown": "handlePointerDown($event)", "focus": "handleFocus($event)", "blur": "handleBlur($event)", "click": "handleClick($event)" }, properties: { "id": "triggerId()", "attr.aria-describedby": "isOpen() ? rootContext()?.contentId : undefined", "attr.data-popup-open": "triggerInteraction.dataPopupOpen()", "attr.data-trigger-disabled": "triggerInteraction.disabled() ? \"\" : undefined", "attr.data-rdx-tooltip-trigger": "isDisabled() ? undefined : \"\"" } }, hostDirectives: [{ directive: i1.RdxPopperAnchor }], ngImport: i0 }); }
|
|
732
836
|
}
|
|
733
837
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: RdxTooltipTrigger, decorators: [{
|
|
734
838
|
type: Directive,
|
|
@@ -740,14 +844,18 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
|
|
|
740
844
|
'data-grace-area-trigger': "''",
|
|
741
845
|
'[id]': 'triggerId()',
|
|
742
846
|
'[attr.aria-describedby]': 'isOpen() ? rootContext()?.contentId : undefined',
|
|
743
|
-
'[attr.data-popup-open]': '
|
|
744
|
-
'[attr.data-trigger-disabled]': '
|
|
847
|
+
'[attr.data-popup-open]': 'triggerInteraction.dataPopupOpen()',
|
|
848
|
+
'[attr.data-trigger-disabled]': 'triggerInteraction.disabled() ? "" : undefined',
|
|
849
|
+
'[attr.data-rdx-tooltip-trigger]': 'isDisabled() ? undefined : ""',
|
|
850
|
+
'(pointerenter)': 'handlePointerEnter($event)',
|
|
745
851
|
'(pointermove)': 'handlePointerMove($event)',
|
|
746
852
|
'(pointerleave)': 'handlePointerLeave()',
|
|
853
|
+
'(mouseover)': 'handleMouseOver($event)',
|
|
854
|
+
'(mouseleave)': 'handleMouseLeave()',
|
|
747
855
|
'(pointerdown)': 'handlePointerDown($event)',
|
|
748
|
-
'(focus)': 'handleFocus()',
|
|
749
|
-
'(blur)': 'handleBlur()',
|
|
750
|
-
'(click)': 'handleClick()'
|
|
856
|
+
'(focus)': 'handleFocus($event)',
|
|
857
|
+
'(blur)': 'handleBlur($event)',
|
|
858
|
+
'(click)': 'handleClick($event)'
|
|
751
859
|
}
|
|
752
860
|
}]
|
|
753
861
|
}], ctorParameters: () => [], propDecorators: { handle: [{ type: i0.Input, args: [{ isSignal: true, alias: "handle", required: false }] }], payload: [{ type: i0.Input, args: [{ isSignal: true, alias: "payload", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], closeOnClick: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnClick", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], delay: [{ type: i0.Input, args: [{ isSignal: true, alias: "delay", required: false }] }], closeDelay: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeDelay", required: false }] }], userOnPointerDown: [{ type: i0.Input, args: [{ isSignal: true, alias: "rdxOnPointerDown", required: false }] }] } });
|